CSP-J模拟赛补题4

日期:2024年10月4日

学号:S14738

一、我的总分:
T1【三个(three)】:40分

T2【合体(fit)】:10分

T3【矩阵(matrix)】:5分

T4【数对(pair)】:5分

二、比赛概况:
T1【三个(three)】:

        考试的时候脑子大概是进水了,数据量那么大,都想到long long了,偏偏就忘了%2。

T2【合体(fit)】:

        也不太会啊,想到了用桶,但是时间超限了,应该是循环太多了。

T3【矩阵(matrix)】:

        读完题第一个反应就是绝对时间超限了,用了5层嵌套循环,时间大概是O(243*10^10),只得了5分。

T4【数对(pair)】:

        读完题懵懵的,感觉挺难,直接蒙代码,至少对了一个样例。

三、比赛分析:

T1【三个(three)】:

1、题目大意

        现在科学家在培养 A,B,C 三种微生物,这三种微生物每一秒都会繁殖出新的微生物,具体规则为:

                A 类微生物每一秒会繁殖出 1 个 A 类微生物,1 个 B 类微生物,1 个 C 类微生物。
                B 类微生物每一秒会繁殖出 2 个 A 类微生物,2 个 C 类微生物。
                C 类微生物每一秒会繁殖出 1 个 A 类微生物,1 个 B 类微生物。

        假设所有的微生物都不会死亡,一开始培养皿中有 A,B,C 三种微生物各 1 个,现在问你 n 秒后 A,B,C 三种微生物分别有奇数个还是偶数个。

2、考试思路

        输入 -> 计算繁殖后个数 -> 输出

3、讲解后思路

        在计算完了%2

4、AC代码

#include<iostream>
#include<cstdio>
using namespace std;
int n,a[1000005],b[1000005],c[1000005];
int main(){
//	freopen("three.in","r",stdin);
//	freopen("three.out","w",stdout);
	cin >> n;
	a[0] = 1;
	b[0] = 1;
	c[0] = 1;
	for(int i = 1;i <= n;i++){
		//计算繁殖后个数,直接 %2得到奇偶性 
		a[i] = (a[i-1]+a[i-1]+b[i-1]*2+c[i-1])%2;
		b[i] = (b[i-1]+a[i-1]+c[i-1])%2;
		c[i] = (c[i-1]+a[i-1]+b[i-1]*2)%2;
	}
	//根据题目要求输出 
	if(a[n] == 1){
		cout << "odd";
	}else{
		cout << "even";
	}
	cout << endl;
	if(b[n] == 1){
		cout << "odd";
	}else{
		cout << "even";
	}
	cout << endl;
	if(c[n] == 1){
		cout << "odd";
	}else{
		cout << "even";
	}
//	fclose(stdin);
//	fclose(stdout);
	return 0;
}

T2【合体(fit)】:

1、题目大意

        现在有 n 个大小范围在 1∼m 中的整数 a_​1​​∼a_​n​​,并且你获得了一项魔法能力。
施加一次魔法能力后,可以将两个相同的数字合并成一个数字,并且这个数字为原来的数字 +1,例如:

                有 2,2 这两个数字,施加一次魔法能力后可以将这两个数字合并成一个数字 3。

        现在有 q 次询问,每次询问给你一个整数 x,你可以施加任意次数魔法能力,问你这 n 个整数最多能得到多少个整数 x ?

2、考试思路

        思路不太对,但是想到了桶

3、讲解后思路

        输入 -> 计算合成几个x打表 -> 输入问题 -> 输出

4、AC代码

#include<iostream>
#include<cstdio>
using namespace std;
int n,m,num[1000005],q,t[1000005],ans[1000005];
int main(){
//	freopen("fit.in","r",stdin);
//	freopen("fit.out","w",stdout);
	scanf("%d%d",&n,&m);
	for(int i = 1;i <= n;i++){
		scanf("%d",&num[i]);
		//运用桶 
		t[num[i]]++;
	}
	for(int i = 1;i <= m;i++){
		//计算能合成几个 i 
		ans[i] = t[i]+ans[i-1]/2;
	}
	scanf("%d",&q);
	for(int i = 1;i <= q;i++){
		int x;
		scanf("%d",&x);
		printf("%d\n",ans[x]);
	}
//	fclose(stdin);
//	fclose(stdout);
	return 0;
}

T3【矩阵(matrix)】:

1、题目大意

        现在给你一个 n 行 m 列的矩阵,矩阵上每个格子有一个整数,其中第 i 行第 j 列对应的格子上的整数为 g[​i,j​​] 。
        现在定义该矩阵的一个子矩阵的快乐值为该子矩阵上的所有数字的异或和。

        一组数字 a_1,a_2,...,a_n​​ 的异或和为a_1 ^ a_2 ^ ... ^ a_n。

        现在问你,该矩阵的所有子矩阵的快乐值之和为多少?

2、考试思路

        循环出每一个子矩阵并^出答案

3、讲解后思路

        输入 -> 遍历并记录个数,计算sum -> 输出

4、AC代码

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
using namespace std;
int n,m,a[305][305],t[305],tt[305];
int main(){
//	freopen("matrix.in","r",stdin);
//	freopen("matrix.out","w",stdout);
	cin >> n >> m;
	for(int i = 1;i <= n;i++){
		for(int j = 1;j <= m;j++){
			cin >> a[i][j];
		}
	}
	long long sum = 0;
	//枚举起始行 
	for(int i = 1;i <= n;i++){
		memset(t,0,sizeof(t));
		for(int ii = i;ii <= n;ii++){
			for(int j = 1;j <= m;j++){
				t[j] ^= a[ii][j];
				tt[j] = (tt[j-1] ^ t[j]);
			}
			for(int p = 0;p < 10;p++){
				//记录第 p位为 0(为 1)的个数 
				int c0 = 1,c1 = 0;
				//按位枚举 
				for(int k = 1;k <= m;k++){
					if(tt[k] & (1 << p)){
						sum += 1ll*(1 << p)*c0;
						c1++;
					}else{
						sum += 1ll*(1 << p)*c1;
						c0++;
					}
				}
			}
		}
	}
	cout << sum;
//	fclose(stdin);
//	fclose(stdout);
	return 0;
}

T4【数对(pair)】:

1、题目大意

        给你一个长度为 n 的数列 a_1,a_2,...,a_n。
        再给你一个长度为 m 的数列 b_1,b_2,...,b_m。
        现在再再再给你一个正整数 p,让你生成一个长度为 n×m 的数列 c_1,c_2,...,c_​n×m​​。
        其中满足 c​(i−1)×m+j​​=(a_​i​​+b_​j​​) mod p。
        现在问你数列 c 中有多少个数对 (i,j) 满足 i< j 且 c_i > c_ j ?

2、考试思路

        挺懵的,整了5层嵌套循环,给我整了个运行错误

3、讲解后思路

        输入 -> 打表 -> 计算 -> 输出

4、AC代码

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int N = 1e6+5;
bool flag = 0;
int n,m,p,a[N],b[N];
long long num[10],numb[10],nixu[10],ans[200],cnt = 0;
//压位高精,一个变量存6位 
void jia(long long k){
	ans[0]+=k;
	int pos = 0;
	while(1){
		if(ans[pos] >= 1000000){
			ans[pos+1]+=ans[pos]/1000000;
			ans[pos]%=1000000;
			if(++pos > cnt){
				cnt++;
			}
		}else{
			break;
		}
	}
}
int main(){
//	freopen("pair.in","r",stdin);
//	freopen("pair.out","w",stdout);
	cin >> n >> m >> p;
	for(int i = 1;i <= n;i++){
		cin >> a[i];
		if(a[i] != 0){
			flag = 1;
		}
	}
	for(int i = 1;i <= m;i++){
		cin >> b[i];
		if(b[i] != 0){
			flag = 1;
		}
		numb[b[i]]++;
	}
	//a b数组范围 0~9,打表预处理 
	for(int j = 0;j < p;j++){
		memset(num,0,sizeof(num));
		for(int i = 1;i <= m;i++){
			for(int k = b[i]+1;k < p;k++){
				nixu[j] +=num[k];
			}
			num[b[i]]++;
			b[i] = (b[i]+1)%p;
		}
	}
	memset(num,0,sizeof(num));
	for(int i = 1;i <= n;i++){
		jia(nixu[a[i]]);
		for(int j = 0;j < p;j++){
			//某一个c的值 
			int x = (j+a[i])%p;
			for(int k = x+1;k < p;k++){
				long long x = 1ll*numb[j]*num[k];
				jia(x);
			}
		}
		for(int j = 0;j < p;j++){
			num[(j+a[i])%p]+=numb[j];
		}
	}
	if(!flag){
		cout << 0;
	}else{
		cout << ans[cnt];
		for(int i = cnt-1;i >= 0;i--){
			printf("%06lld",ans[i]);
		}
	}
//	fclose(stdin);
//	fclose(stdout);
	return 0;
}

四、反思&总结:

        前两题瞄准100分,后两题做不了就找特殊数据骗分。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值