JZOJ 2019.06.01【NOIP普及组】模拟赛C组

2019.06.01【NOIP普及组】模拟赛C组

超链接为pdf题面,请先登录。

有故障的打字机

一看了数据范围,就应该想到找规律了。在推一推,你会发现,这道题如果不用高精度的话,绝对炸裂!
而有一些“Lucky dog”就是往死里钻→
Lucky dog
首先用暴力试一试,将n<=10的解算出来,然后找规律:
JZOJ 2019.06.01【NOIP普及组】模拟赛C组_第1张图片
大家有没有发现,每一个解要么以1结尾,要么以9结尾。
我就是这样想出规律的:
当n=1时,ans=101-91
当n=2时,ans=102-92
当n=3时,ans=103-93
则ans=10n-9n
高精乘请看最后一个题目。
LAW code:

#include
using namespace std;
int str,n,a[2010];
int main()
{
//	freopen("typewrt.in","r",stdin);
//	freopen("typewrt.out","w",stdout);
	scanf("%d",&n);
	a[1]=1;
	if(n==1)
	{
		printf("1\n");
		return 0;
	}
	for(int i=2;i<=n;i++)
	{
		for(int j=1;j<=1500;j++)
		{
			a[j]=a[j]*9+a[j-1]/10;
			a[j-1]%=10;
		}
		a[i]++;
		str=1500;
		while(!a[str])
			str--;
	}
	for(int i=str;i>=1;i--)
		printf("%d",a[i]);
	printf("\n");
	fclose(stdin);
	fclose(stdout);
	return 0;	
}

1497. 最大约数和

一个裸尾巴的背包问题,每个数的大小可以看作是物品的重量,每个数的约数和可以看作是物品的价值,然后就用常规01背包,就可以了。
背包问题知识点超链接

#include
#include
#define max(a,b) ((a)>(b)?(a):(b))
using namespace std; 
int sum[1010],n,mx; 
int f[1010];
int ys(int x) 
{
	int i,sum=0; 
	for(i=1;i<x;i++) 
		if(x%i==0)
			sum+=i; 
	return sum; 
} 
void dp() 
{	
    for(int i=1;i<=n;i++)
    	for(int j=n;j>=i;j--)
    		f[j]=max(f[j],f[j-i]+sum[i]);
	for(int i=1;i<=n;i++)
    	if(f[i]>mx)            
			mx=f[i]; 
}                                
int main()
{ 
//	freopen("maxsum.in","r",stdin);
//	freopen("maxsum.out","str",stdout);
    scanf("%d",&n);  
	for(int i=2;i<=n;i++)                
		sum[i]=ys(i);             
    dp(); 
    printf("%d\n",mx);
    fclose(stdin);
    fclose(stdout);
   	return 0; 
}
//每个数的大小可以看作是物品的重量,每个数的约数和可以看作是物品的价值

1498. 流感会结束吗

队列的应用与实现。首先大家需要掌握几个重要队列函数。
首先,在代码上打上头文件 #include< queue >
常用的成员函数如下:

  1. push
  2. pop
  3. size
  4. empty
  5. front
  6. back
push:

队列中由于是先进先出,push即在队尾插入一个元素,如:

queue<string> q;
q.push("Hello World!");
q.push("China");
cout<<q.front()<<endl;

可以输出:Hello World!

pop:

将队列中最靠前位置的元素拿掉,是没有返回值的void函数。如:

queue<string> q;
q.push("Hello World!");
q.push("China"); 
q.pop();
cout<<q.front()<<endl;
size:

返回队列中元素的个数,返回值类型为unsigned int。如:

queue q;
cout<<q.size()<<endl;
q.push(“Hello World!);
q.push(“China”);
cout<<q.size()<<endl;
empty

判断队列是否为空的,如果为空则返回true。如:

1 queue q;
2 cout<<q.empty()<<endl;
3 q.push(“Hello World!);
4 q.push(“China”);
5 cout<<q.empty()<<endl;
front

返回值为队列中的第一个元素,也就是最早、最先进入队列的元素。注意这里只是返回最早进入的元素,并没有把它剔除出队列。如:

queue<string> q;
q.push("Hello World!");
q.push("China");
cout<<q.front()<<endl;
q.pop();
cout<<q.front()<<endl;

输出值为两行,分别是Hello World!和China。只有在使用了pop以后,队列中的最早进入元素才会被剔除。

back

返回队列中最后一个元素,也就是最晚进去的元素。如:

queue q;
q.push(“Hello World!);
q.push(“China”);
cout<<q.back()<<endl;

输出值为China,因为它是最后进去的。这里back仅仅是返回最后一个元素,也并没有将该元素从队列剔除掉。
QUE code:

#include
#include
using namespace std;
const int N=100050;
queue<int> q;
int a,n,m,tot=0,sj[N],ans;
int last[N],zk[N];//1:生病 0:可感染 2:抗感染 
struct node{
	int next,to;
}edge[2*N];
void add(int to,int sta){
	edge[++tot].to=to;
	edge[tot].next=last[sta];
	last[sta]=tot;
	edge[++tot].to=sta;
	edge[tot].next=last[to];
	last[to]=tot;
}
int main(){
	freopen("flu.in","r",stdin);
	freopen("flu.out","w",stdout);
	scanf("%d %d",&n,&m);
	for(int i=1;i<=m;i++){
		int x,y;
		scanf("%d %d",&x,&y);
		add(y,x);
	}
	scanf("%d",&a);
	q.push(a);zk[a]=1;sj[a]=1;
	while(!q.empty()){
		int i=q.front();q.pop();
		ans=max(ans,sj[i]);
//		printf("%d号学生 状况:%d 时间:%d\n",i,zk[i],sj[i]);
		for(int j=last[i];j;j=edge[j].next){
			if(!zk[edge[j].to] && sj[edge[j].to]<=sj[i]){
				q.push(edge[j].to);
				zk[edge[j].to]=1;
				sj[edge[j].to]=sj[i]+1;
				//printf("%d号学生 状况:%d 时间:%d\n",edge[j].to,zk[edge[j].to],sj[edge[j].to]);
			}
		}
		zk[i]=2;sj[i]++;
	}
	printf("%d",ans);
	return 0;
}

1896.公牛数学

裸高精度,十分容易。
对于高精乘高精,请观察一下图片:
高精乘高精
分析c数组下标的变化规律,可以写出如下关系式:ci = c’i +c”i +…由此可见,c i跟a[i]*b[j]乘积有关,跟上次的进位有关,还跟原c i的值有关,分析下标规律,有c[i+j-1]= a[i]*b[j]+ x + c[i+j-1]; x=c[i+j-1]/10 ; c[i+j-1]%=10;
以上为dalao lzoi_hmh 的资料。
HPM code:

#include
#include
#include  
using namespace std;  
char str1[50],str2[50];  
int a[50],b[50],c[100],len; 
int main()  
{  
//  	freopen("bullmath.in","r",stdin);
//  	freopen("bullmath.out","w",stdout);   
	scanf("%s",&str1);
	scanf("%s",&str2); 
  	a[0]=strlen(str1); 
  	b[0]=strlen(str2); 
  	for(int i=1;i<=a[0];i++)  
    	a[i]=str1[a[0]-i]-'0';  
  	for(int i=1;i<=b[0];i++)  
    	b[i]=str2[b[0]-i]-'0';  
  	for(int i=1;i<=a[0];i++)  
    	for(int j=1;j<=b[0];j++)  
    	{  
    		c[i+j-1]+=a[i]*b[j];  
    		c[i+j]+=c[i+j-1]/10;  
    		c[i+j-1]%=10;     
    	}  
  	len=a[0]+b[0]+1; 
  	while((!c[len])&&(len>1))
	  	len--;   
  	for(int i=len;i>=1;i--)  
    	printf("%d",c[i]);
    printf("\n");
    fclose(stdin);
    fclose(stdout);
  	return 0;   
}  

你可能感兴趣的:(比赛题解)