#1615. 题面

题面

No testdata at current.

2024年语法周赛13题解

T1 变形虫

本题主要考查循环和条件判断的使用。

只要蛋糕的重量和变形虫当前的重量相同,变形虫重量变量变两倍即可。需要注意一下,重量有可能超出int范围

#include<bits/stdc++.h>
using namespace std;
int main(){
	long long sum=0,a,n,ch[205];
	cin>>a>>n;
	for(int i=1;i<=n;i++){
		cin>>ch[i];
		if(a==ch[i])a*=2;
	}
	cout<<a;
	return 0;
	
}

T2 海明码

从0开始一直递增枚举满足条件的数,判断这个数和之前的所有满足条件的数,是否两两之间满足条件。可以用异或符号直接算两个数不同位的结果,然后分解成二进制数统计有几个1即可。也可以两个数一起转二进制,在过程中统计不同位数。

参考代码 100分

#include<bits/stdc++.h>
using namespace std;
int n,d;
int a[70],lens,num;
int check(int x,int y)
{
    int k=x^y,ans=0;
    while(k>0)
    {	if(k%2)
        ans++;
        k/=2;
    }
    return ans;
}
int main()
{
    bool flag=1;
    scanf("%d%d",&n,&d);
    while(lens<n)
    {
        flag=1;
        for(int i=1;i<=lens;++i)
            if(check(a[i],num)<d) flag=0;
        if(flag) a[lens++]=num;
        num++; 
    }
    for(int i=1;i<=n;++i)
    {
        printf("%d ",a[i-1]);
        if((i%10)==0) cout<<endl;
    }
    return 0;
}

T3 自创除法

部分分做法:双重循环枚举数字的每一位,按位相除进行累加即可,注意数位为零时跳过累加即可

#include <iostream>
using namespace std;
int main()
{
    long long a,b,a1,b1;
	double sum=0;
	
    cin>>a>>b;
    a1=a,b1=b;
    while(a1!=0)
    {	
		if(a1%10==0){
	    	a1/=10;
	        b1=b;
	    	continue;
	}
        while(b1!=0)
        {	if(b1%10==0){
        	b1/=10;
        	continue;
		}
            sum+=double(a1%10)/double(b1%10);
            b1/=10;
        }
        a1/=10;
        b1=b;
    }
    printf("%.2lf",sum);
    
    return 0;
}

满分做法:把数字当成字符串处理,双重循环遍历数字的每一位。数字字符减去‘0’转数字,进行数位相除累加,依旧是要注意数位为零时,跳过不计算,否则会运行错误。

#include<bits/stdc++.h>
using namespace std;
char s1[1000000],s2[10000000];
double sum=0;
int main(){
	sum=0;
	scanf("%s%s",s1,s2);
	for(int i=0;i<strlen(s1);i++){
	
		if(s1[i]=='0')continue;
		
		for(int j=0;j<strlen(s2);j++){
			if(s2[j]=='0')continue;
			sum+=double(s1[i]-'0')/double(s2[j]-'0');
		}
	}
	printf("%.2lf\n",sum);
	return 0;
}

T4 约瑟夫升级版

题意:每个人按照输入的顺序排成一圈,每个人都有他们独特的id。从1数到m,在1-m范围内报到 反序素数的出圈

部分分做法:模拟约瑟夫环,从1报数到m,报到反序素数就b数组标记为出圈。报数的人位置不停移动,到达队尾就从头再来。判断反序素数使用平常经常使用的判断素数和颠倒数字的方法,但是因为调用函数过多,会超时。

#include<bits/stdc++.h>
using namespace std;
int cnt,n,m,sum,shu=0,weizhi=1;
bool b[10000010];
long long a[10000000];
bool isprime(long long n){
	if(n<2)return 0;
	for(int i=2;i*i<=n;i++){
		if(n%i==0)return 0;
	}
	return 1;
}
int reverse(int n){
	int sum=0;
	while(n){
		sum=sum*10+n%10;
		n/=10;
	}
	return sum;
}
int main(){
	sum=0,shu=0,weizhi=1;
	memset(b,0,sizeof(b));
	
	cin>>n>>m;
	
	for(int i=1;i<=n;i++){
		scanf("%lld",&a[i]);
	}
	
	while(sum<n){
		if(b[weizhi]==0){
			shu++;
			if(isprime(shu)==1&&isprime(reverse(shu))==1){
				
				sum++;
				b[weizhi]=1;
				cout<<a[weizhi]<<" ";
			}
			if(shu>=m)shu=0;
		}
		weizhi++;
		if(weizhi>n)weizhi=1;
	}
	return 0;
}

满分做法:使用筛选法找素数,提前把素数的状态标记在isprme数组里,直接访问即可知道。

#include<bits/stdc++.h>
using namespace std;
int prime[10000000],cnt,n,m,sum,shu=0,weizhi=1;
bool isprime[100000000],b[10000010];
long long a[10000000];
void init(int n){
	isprime[1]=1;
	for(int i=2;i<=n;i++){
		if(!isprime[i])prime[++cnt]=i;
		for(int j=1;j<=cnt&&i*prime[j]<=n;j++){
			isprime[i*prime[j]]=1;
			if(i%prime[j]==0)break;
		}
			
	}
}
int reverse(int n){
	int sum=0;
	while(n){
		sum=sum*10+n%10;
		n/=10;
	}
	return sum;
}
int main(){
	sum=0,shu=0,weizhi=1;
	memset(b,0,sizeof(b));
	memset(isprime,0,sizeof(isprime));
	cin>>n>>m;
	init(10000000);
	for(int i=1;i<=n;i++){
		scanf("%lld",&a[i]);
	}
	
	while(sum<n){
		if(b[weizhi]==0){
			shu++;
			if(isprime[shu]==0&&isprime[reverse(shu)]==0){
				
				sum++;
				b[weizhi]=1;
				cout<<a[weizhi]<<" ";
			}
			if(shu>=m)shu=0;
		}
		weizhi++;
		if(weizhi>n)weizhi=1;
	}
	return 0;
}