NOI Online 2022 入门组

NOI Online 2022 入门组,第1张

NOI Online 2022 入门组 题目 T1 王国比赛

智慧之王 Kri统治着一座王国。这天 Kri决定举行一场比赛,来检验自己大臣的智慧。
比赛由 n道判断题组成,有 m位大臣参加。
现在你已经知道了所有大臣的答题情况,但尚未拿到答案,于是你决定先行预测。
具体来说,对于第 i道题,有 x 个大臣选对,y 个大臣选错(显然有 x+y=m),如果 x>y,那么你预测这题答案为对,否则为错。
为了方便,我们保证 m是奇数。
在统计完成后,你拿到了答案,你想知道通过你的预测方式你最后有几道题预测正确。
输入格式
第一行两个正整数 n,m,保证 m是奇数。
接下来 m行,每行 n 个整数,第 i 行第 j 个整数 aij 代表第 i 位大臣对第 j 道题的答案,1 表示他选对,0表示他选错。
接下来 1行 n 个整数, 表示比赛答案,第 i 个数 bi 若为 1 表示第 i 道题答案是对,若为 0表示答案是错。
输出格式
输出一个整数,表示你最后有几题预测正确。
数据范围
对于 20%的数据,1≤n≤5,m=1。
对于 50% 的数据,1≤n≤10,1≤m≤10。
对于 100% 的数据,1≤n≤1000,1≤m≤1000,m为奇数。
输入样例1:
3 3
1 0 1
0 1 1
0 1 0
1 1 1
输出样例1:
2
样例1解释
第一题 x=1,y=2
你预测答案为错(即 0),实际答案为 1,预测错误。
第二题 x=2,y=1
你预测答案为对(即 1),实际答案为 1,预测正确。
第三题 x=2,y=1
你预测答案为对(即 1),实际答案为 1,预测正确。
所以预测正确的题数为 2。
输入样例2:
6 5
1 0 1 1 1 0
0 1 0 1 1 1
0 0 1 0 1 0
1 0 1 0 1 0
0 1 0 1 0 0
1 0 1 0 1 0
输出样例2:
4

解题思路

#include 
using namespace std;
//王国比赛
const int N = 1005;
int n,m;// n questions
bool result[N][N];
int ans=0;

int main()
{
	scanf("%d %d",&n,&m);
	for(int i = 1; i <= m + 1; i ++)
	  for(int j = 1; j < n + 1; j ++)
	   {
	   	cin >> result[i][j]; 
	   }
	   
	for(int i = 1; i <= n ; i ++)
	{
	  bool a = false;
	  int sum = 0;
	  for(int j = 1; j <= m; j ++)
	     sum += result[j][i];
	   
	  if(sum > m / 2) a = true;
	  ans += (!a) ^ result[m + 1][i];
	}

    cout << ans << endl;
	   

  return 0;
}

T2 数学游戏

Kri喜欢玩数字游戏。一天,他在草稿纸上写下了 t对正整数 (x,y),并对于每一对正整数计算出了 z=x×y×gcd(x,y)。
可是调皮的 Zay找到了 Kri 的草稿纸,并把每一组的 y 都擦除了,还可能改动了一些 z。
现在 Kri想请你帮忙还原每一组的 y,具体地,对于每一组中的 x 和 z,你需要输出最小的正整数 y,使得 z=x×y×gcd(x,y)。
如果这样的 y不存在,也就是 Zay 一定改动了 z,那么请输出 −1。
注:gcd(x,y)
表示 x 和 y 的最大公约数,也就是最大的正整数 d,满足 d 既是 x 的约数,又是 y的约数。
输入格式
第一行一个整数 t,表示有 t 对正整数 x 和 z。
接下来 t行,每行两个正整数 x 和 z,含义见题目描述。
输出格式
对于每对数字输出一行,如果不存在满足条件的正整数 y,请输出 −1,否则输出满足条件的最小正整数 y。
数据范围
对于 20%的数据,1≤t,x,z≤103
对于 40% 的数据,1≤t≤103,1≤x≤106,1≤z≤109
对于另 30% 的数据,1≤t≤10^4。
对于另 20% 的数据,1≤x≤10^6。
对于 100% 的数据,1≤t≤5×105,1≤x≤109,1≤z<2^63。
输入样例1:
1
10 240
输出样例1:
12
样例1解释
x×y×gcd(x,y)=10×12×gcd(10,12)=240。
输入样例2:
3
5 30
4 8
11 11
输出样例2:
6
-1
1

解题思路

#include 
#include 
using namespace std;
//math game
//数论构造题 
//构造 d = gcd(x,y); d^2 = gcd(x^2,z/x) 
typedef long long LL;
int t;
LL z,x;
LL qd2;

LL gcd(LL a, LL b)
{
	return  b ? (gcd(b, a % b)) : a ;
}
 
 
int main()
{
	cin >> t;
	while(t --)
	{
	    scanf("%lld%lld",&x,&z);		
		if(z % x){
			puts("-1");
			continue;
		}else qd2 = z / x;
		 
		register LL d2 = gcd(x * x, qd2);
		register LL d = sqrt(d2);
		if(d * d < d2){
			puts("-1");
			continue;
		}
	
		cout << qd2 / d <<'\n'; 	
	}

  return 0;
}

T3 字符串

Kri 非常喜欢字符串,所以他准备找 t 组字符串研究。第 i 次研究中, Kri 准备了两个字符串 S 和 R,其中 S 长度为 n ,且只由 0、1、- 三种字符构成(注:这里的第三种字符是减号), R 初始时为空。
每次研究,Zay 会带着一个美丽的长度为 m 的字符串 T 来找 Kri 玩,Kri 非常羡慕 Zay 拥有如此美丽的字符串,便也想用字符串 S 和 R 变出字符串 T。
具体地,Kri 将会进行 n 次 *** 作。每次 *** 作中,Kri 会取出 S 的第一个字符(记为 c),并将其从 S 中删去。如果 c= -,则 Kri 要删去 R 的开头字符或结尾字符(数据保证删去后 R 不为空)。否则,Kri 会将 c 加入到 R 的末尾。
当进行完所有 *** 作后,Kri 会检查 R 是否和 T 相等。如果 R=T,Kri 就会感到开心;否则,Kri 会感到难受。
请问在每次研究中,Kri 有多少种 *** 作方式使自己最后感到开心?我们定义两种方案不同,当且仅当在某种方案的某次 *** 作中,Kri 删去了 R 的开头字符。而在另一种方案的这次 *** 作中,Kri 删去了 R 的结尾字符。
由于答案可能很大,你只需要输出答案除以 1,000,000,007(即 10^9+7 )的余数。
输入格式
第一行一个正整数 。
接下来有 t 组数据分别表示 t 次字符串的研究,对于每组数据:
第一行有两个正整数 n,m,分别表示字符串 S,T 的长度。
第二行是字符串 S。
第三行是字符串 T。
输出格式
共 t 行,第 i 行表示第 i 组研究的答案。
输入样例1:
3
6 2
10-01-
01
7 3
010-1-1
101
6 4
111-00
1100
输出样例1:
2
1
2
说明/提示
【样例 1 解释】
对于第一组数据,有以下两种方案:
第一个 - 删 R 的开头,第二个 - 删 R 的开头。
第一个 - 删 R 的结尾,第二个 - 删 R 的开头。

【数据范围】
对于 20% 的数据,n,m≤15。
对于 30% 的数据,n,m≤30。
对于 70% 的数据,n,m≤80。
对于另 10% 的数据,保证答案不超过 1。
对于100% 的数据,1≤t≤5,1≤n,m≤400。

解题思路

#include 
#include 
#include 
using namespace std;


const int p = 1e9 + 7;
int K, n, m, cnt, dp[410][410][410];

char s[410],t[410];
int main () {
	cin >> K;
	
	while (K --) {
		scanf("%d%d",&n,&m);
		scanf("%s", s + 1);
		scanf("%s", t + 1);
	    
		cnt = 0;//统计'-'的数量
		
		for (int i = 1; i < n + 1; i ++) 
			if (s[i] == '-') cnt ++;
			
		if (n - cnt * 2 != m) {
			cout << 0 << endl;
			continue;
		}
		
		int len = 0;//r开始为空串 
		memset(dp, 0, sizeof dp);
		dp[0][0][0] = 1;
		
		for (int i = 1; i <= n; i ++) {
			if (s[i] == '-')
				len --;
			else
				len ++;
			for (int j = 0; j <= cnt; j ++) {
				for (int k = 0; k <= cnt - j; k ++) {
					if (s[i] == '-') {
						dp[i][j][k] = (dp[i - 1][j + 1][k] + dp[i - 1][j][k + 1]) % p;
					} else {
						if (k > 0)
							dp[i][j][k] = dp[i - 1][j][k - 1];
						if (k == 0 && t[len - j] == s[i])
							dp[i][j][k] = dp[i - 1][j][k];
						if (len == j)
							dp[i][j][k] = (dp[i][j][k] + dp[i - 1][j - 1][k]) % p;
					}
				}
			}
		}
		printf("%d\n", dp[n][0][0]);
	}
	return 0;
}

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/869443.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-13
下一篇 2022-05-13

发表评论

登录后才能评论

评论列表(0条)

保存