第二次练习总结

第二次练习总结

  • 对新手来说 这个题确实有些难了

AC代码(别照抄)

A Yes OK

  • 位与 移位 提取整数的指定位
#include <stdio.h>
int main(void){
	int T,n,k;
	scanf("%d",&T);
	while(T--){
		scanf("%d%d",&k,&n);
		puts(k & (1 << n)?"Yes!":"NO!");

	}
	return 0;
}

B 循环移位

  • 注意数据范围 移出去了要有地方能接住
  • 可以用数组模拟(但是不推荐)
  • 可以循环(参考下面某同学的代码)
#include<stdio.h>

int main(){
	int N,k,i;
	unsigned long long a,a1;

	while((scanf("%d%d%llu",&N,&k,&a)) != EOF){
		k %= N;
		for(i = 0;i < k;i++){
			a1 = a;
			a1 &= 1ll << (N - 1);
			a <<= 1ll;
			if(a1 != 0){
				a |= 1;
			}
			a &= (1ll << N) - 1;
		}
		printf("%llu\n",a);
	}
	return 0;
}
  • 也可以一行代码秒了这个题(存好模板 循环左移同理 各位可以想下)
#include <stdio.h>
#define CROL(X,i,n) ((((X)<<(i))|((X)>>((n)-(i))))&((1ull<<(n))-1ull))
//可以写上面的宏
//或者下面的函数
long long crol_ull(long long a,long long n,long long k){//对n位的二进制数a循环移位k次
	return ((a << k | (a >> (n - k))) & ((1ll << n) - 1ll));
}
int main(){
    unsigned long long n,k,a;
	while(~scanf("%llu%llu%llu",&n,&k,&a)){
		k = k % n;
		printf("%llu\n",CROL(a,k,n));
	}
    return 0;
}

C 复数计算器

  • 复数计算是重点
  • 分类讨论得全面
  • 格式化输出(用不好就得多分类讨论+if-else)
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
double eps = 1e-8;
int eq(double x,double y){
	return fabs(x - y) < eps;
}
int isint(double x){
	return fabs(round(x) - x) < eps;
}
int main(int argc,char **argv){
	double a,b,c,d,x = .0,y = .0;
	char op;
	while(~scanf("(%lf%lfi)%c(%lf%lfi)\n",&a,&b,&op,&c,&d)){
		switch(op){
		case '+':
			x = a + c;y = b + d;break;
		case '-':
			x = a - c;y = b - d;break;
		case '*':
			x = a * c - b * d;y = b * c + a * d;break;
		case '/':
			x = (a * c + b * d) / (c * c + d * d);
			y = (b * c - a * d) / (c * c + d * d);
			break;
		}
		//out:x+iy
		if(eq(x,0.0)){//real==0
			if(eq(y,0.0)){//real==0;imag==0
				puts("0");
			}
			else if(eq(y,1.0)){
				puts("i");
			}
			else if(eq(y,-1.0)){
				puts("-i");
			}
			else if(isint(y)){
				printf("%.0fi\n",y);
			}
			else{
				printf("%.2fi\n",y);
			}
		}
		else{//先real再imag
			if(isint(x)){
				printf("%.0f",x);
			}
			else{
				printf("%.2f",x);
			}
			if(!eq(y,0.0)){
				if(eq(y,1.0)){
					printf("+i");
				}
				else if(eq(y,-1.0)){
					printf("-i");
				}
				else if(isint(y)){
					printf("%+.0fi",y);
				}
				else{
					printf("%+.2fi",y);
				}
			}

			putchar('\n');
		}
	}
	return 0;
}

D 进制回文数

  • cbj进制转换的升级版 思路类似
  • 读进来的是10进制就很舒服(可以思考下如果不是10进制输入该怎么办)
#include <stdio.h>
int main(){
	int radix,num,i = 0,m,n,flag = 1;
	char buffer[200] = {0};
	char keys[40] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
	scanf("%d",&radix);
	while(~scanf("%d",&num)){
		i = 0;flag = 1;
		while(num){
			buffer[i] = keys[(num % radix)];
			i++;
			num /= radix;
		}
		n = i - 1;
		for(m = 0;m <= n;m++,n--){//验证回文数
			if(buffer[m] != buffer[n]){
				flag = 0;break;
			}
		}
		if(flag){//反着输出
			while(i--){
				putchar(buffer[i]);
			}
			putchar('\n');
		}
	}
	return 0;
}

E 木木枭学高中集合论

  • 枚举,代码填空

  • HINT:如果算法用到了容斥原理,它们的代码主体结构差不多都长成这个样子:

    外层循环跑数,内层循环跑位,然后再加一个右移取位的判断。

  • 注意运算符的优先级 如果不确定可以套一堆括号

#include<stdio.h>
int main(){
	int i,n;
	scanf("%d",&n);
	for(i = 0;i < (1 << n);i++){
		int j;
		for(j = 0;j < n;j++){
			if(((i >> j) & 1) == 1)
				printf("%d",j);
			else{
				printf("-");
			}

		}
		printf("\n");
	}
	return 0;
}

F 高低位

  • GCC编译器有__int128_t类型 可以秒了这个题 但是需要自行解决输出输出问题
  • 如果你的电脑上有linux或者win10和最新的gcc for windows那么 赶 紧 存 模 板
#include <stdio.h>
void write128(__int128_t a){
    if(a < 0){
        putchar('-');a = -a;
    }
    if(a > 9)write128(a / 10);
    putchar(a % 10 + '0');
}
__int128_t read128(){
    __int128_t k = 0,sgn = 1;
    char ch = getchar();
    while(!isdigit(ch)){
        if(ch == '-')sgn = -1;
        ch = getchar();
    }
    while(isdigit(ch)){
        k = (k << 1) + (k << 3) + (ch - '0');
        ch = getchar();
    }
    return k * sgn;
}
int main(){
    __int128_t a,b,c,d,sum;
    a = read128();b = read128();c = read128();d = read128();
    a = (a << 64) | b;c = (c << 64) | d;
    sum = a + c;
    if(sum != ((__int128_t)0x8000000000000000 << 64)){
        write128(sum);
    }
    else{
        puts("-170141183460469231731687303715884105728");
    }
    return 0;
}
  • 数组模拟也行 就是有亿点费劲
#include<stdio.h>

int main(){
	unsigned long long num1w,num1s,num2w,num2s;
	int a[128]={0},b[128]={0},c[128]={0};
	int i=0;
	int d[128]={0},x[128]={0};
	int k=0,t=0;
	int sum=1;
	scanf("%llu%llu",&num1w,&num1s);
	scanf("%llu%llu",&num2w,&num2s);
	while(num1s>0){
		a[i]=num1s%2;
		num1s=num1s/2;
		i++;
	}
	i=0;
	while(num2s>0){
		b[i]=num2s%2;
		num2s=num2s/2;
		i++;
	}
	i=64;
	while(num1w>0){
		a[i]=num1w%2;
		num1w=num1w/2;
		i++;
	}
	i=64;
	while(num2w>0){
		b[i]=num2w%2;
		num2w=num2w/2;
		i++;
	}
	for(i=0;i<127;i++){
		c[i]=c[i]+a[i]+b[i];
		if(c[i]>=2){
			c[i]=c[i]-2;
			c[i+1]=1;
		}
	}
	c[127]=c[127]+a[127]+b[127];
	if(c[127]==3||c[127]==1){
		c[127]=1;
		for(i=0;i<128;i++){
			if(c[i]==1){
				c[i]=0;
			}else{
				c[i]=1;
			}
		}
		c[0]=c[0]+1;
		for(i=0;i<128;i++){
			if(c[i]==2){
				c[i]=0;
				c[i+1]+=1;
			}
		}
		printf("-");
		while(sum>0){
			i=127;
			for(i;i>=0;i--){
				while(t<10){
					t=(t<<1)+c[i];
					i--;
					if(i==-1){
						break;
					}
				}
				if(i==-1){
					if(t<10){
						break;
					}
				}
				i++;
				d[i]=1;
				t=t-10;
			}
			x[k]=t;
			t=0;
			k++;
			sum=0;
			for(i=0;i<128;i++){
				c[i]=d[i];
				sum+=c[i];
			}
			for(i=0;i<128;i++){
				d[i]=0;
			}		
		}
		for(k=k-1;k>=0;k--){
			printf("%d",x[k]);
		}	
	}else{
		c[127]=0;
	}
	while(sum>0){
		i=127;
		for(i;i>=0;i--){
			while(t<10){
				t=(t<<1)+c[i];
				i--;
				if(i==-1){
					break;
				}
			}
			if(i==-1){
				if(t<10){
					break;
				}
			}
			i++;
			d[i]=1;
			t=t-10;
		}
		x[k]=t;
		t=0;
		k++;
		sum=0;
		for(i=0;i<128;i++){
			c[i]=d[i];
			sum+=c[i];
		}
		for(i=0;i<128;i++){
			d[i]=0;
		}	
	}
	for(k=k-1;k>=0;k--){
		printf("%d",x[k]);
	}
	return 0;
}

G CRC16

  • 读取hexadecimal需要在scanf里面使用%x格式控制符 输出也要注意类似问题
#include <stdio.h>
#include <stdlib.h>
int main(){
	int a,CRC = 0xFFFF,c,d,i,flag;
	while(scanf("%X",&a) != EOF){
		CRC = (CRC & (0xff00)) | (((CRC & 0xff) ^ a) & 0xff);
		for(i = 1;i <= 8;i++){
			flag = CRC & 1;
			CRC >>= 1;
			if(flag){
				CRC = CRC ^ 0xA001;
			}
		}
		
	}
	printf("%02X %02X\n",(CRC & 0xff),((CRC & 0xff00) >> 8));
	return 0;
}

H 传接球

  • 输出N0t 1n my team!别打错了
#include <stdio.h>
int main(int argc,char **argv){
	int n,a,b,f;
	int team[101] = {0},chuan[101] = {0},jie[101] = {0};
	scanf("%d",&n);
	while(n--){
		scanf("%d%d",&a,&b);
		if(team[a] == 0){
			team[a] = 1;
		}
		if(team[b] == 0){
			team[b] = 1;
		}
		chuan[a]++;
		jie[b]++;
	}
	scanf("%d",&f);
	if(team[f]){
		printf("%d %d\n",chuan[f],jie[f]);
	}
	else{
		puts("N0t 1n my team!");
	}
	return 0;
}

I 浮点数(1)

  • 照着题意模拟 在纸上比划比划 定好位置会舒服些
  • 位运算可以做
char s[20] = {0};
	int k,E,F,bias,i;
	double f,sgn;
	scanf("%s",s);
	while(~scanf("%d",&k))	{
		E = 0;F = 0;
		bias = (1 << (k - 1)) - 1.;
		if(s[0] == '1')sgn = -1.;
		else sgn = 1;
		for(i = 0;i < k;i++){
			if(s[k - i] == '1'){
				E |= (1 << i);
			}
		}
		for(i = 0;i < 15 - k;i++){
			if(s[15 - i] == '1'){
				F |= (1 << i);
			}
		}
		f = 1.0 + ((double)F / (double)(1 << (15 - k)));
		printf("%.8f\n",f * pow(2.0,E-bias) * sgn);//这里如果用long long转double会出事 必须用pow
	}

J 浮点数(2)

  • 思路类似上面的I题
  • 分数化简 我们以前做过类似的 这里直接粘过来 改了改 包装了一个函数
#include <stdio.h>
int gcd(int a,int b){
	return a % b == 0?b:gcd(b,a % b);
}
void frac(int m,int n,int sign){
	//end preprocess m>0 n>0
	if(m == 0){
		puts("0");
		return;
	}
	int g = gcd(m,n);
	int a = m / g;
	int b = n / g;
	int res = a / b,mod = a % b;
	if(res){
		if(mod){
			if(sign){
				printf("-%d-%d/%d\n",res,mod,b);
			}
			else{
				printf("%d+%d/%d\n",res,mod,b);
			}
		}
		else{
			if(sign){
				putchar('-');
			}
			printf("%d\n",res);
		}
	}
	else{
		if(mod){
			if(sign){
				printf("-%d/%d\n",mod,b);
			}
			else{
				printf("%d/%d\n",mod,b);
			}
		}
	}
}
int main(){
	char s[30] = {0};
	//int m = 16,k = 5,n = 10;
	int bias = 15;//(1<<(5-1))-1
	while(~scanf("%s",s)){
		char se[10] = {0};
		char sf[20] = {0};
		int sign = s[0] == '1',i,e = 0,f = 0;
		strncpy(se,s + 1,5);
		strncpy(sf,s + 6,10);
		for(i = 0;i < 5;i++){
			if(se[5 - i - 1] == '1')e |= (1 << i);
		}
		for(i = 0;i < 10;i++){
			if(sf[10 - i - 1] == '1')f |= (1 << i);
		}
		if(e == 31){
			if(f != 0){
				puts("NaN");
				continue;
			}
			else{
				puts(sign?"-inf":"inf");
				continue;
			}
		}
		else{
			int a,b;
			if(e == 0){
				a = f;
				b = 1 << 24;
			}
			else{
				a = f + (1 << 10);
				b = 1 << 10;
				if(e > bias){
					a *= (1 << (e - bias));
				}
				else{
					b *= (1 << (bias - e));
				}
			}
			//输出约分后的a/b
			frac(a,b,sign);
			memset(s,0,sizeof(s));
		}
	}
	return 0;
}
posted @ 2021-03-25 23:35  仪光19暴毙开发者  阅读(44)  评论(0编辑  收藏  举报