第 45 届国际大学生程序设计竞赛(ICPC)亚洲区域赛(济南),签到题5题

Posted 小哈里

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了第 45 届国际大学生程序设计竞赛(ICPC)亚洲区域赛(济南),签到题5题相关的知识,希望对你有一定的参考价值。

文章目录

补题链接:
https://ac.nowcoder.com/acm/contest/10662

M.Cook Pancakes!

链接:https://ac.nowcoder.com/acm/contest/10662/M
来源:牛客网

题目描述
In China, there is a very famous problem about pancakes: You have a pan and you can fry two pancakes at the same time each time. For a pancake, its front and back sides need to be cooked, and it takes one hour for each side to be cooked.

So how long does it take at least to cook 3 pancakes? The answer is three hours:

In the first hour, fry the front of No.1 pancake and the front of No.2 pancake.

In the second hour, fry the back of No.2 pancake and the front of No.3 pancake.

In the third hour, fry the back of No.1 pancake and the back of No.3 pancake.

Now you have a pan and you can fry KK pancakes at the same time each time. How many hours does it takes at least to cook NN pancakes?

It’s noticed that you have to fry some side of the pancake until fully cooked every time, it means that you can’t fry some side of the pancake half-cooked and taking it out. So the answers are always integers.

输入描述:
The first line has two integers N,KN,K.

1\\leq N,K\\leq 1001≤N,K≤100
输出描述:
Output the answer.
示例1
输入
复制
3 2
输出
复制
3

题意:

  • 煎n个煎饼,每个饼有2两个面,每次能煎k个面,求最少煎几次。(n,k<100)

题解:

  • 如果n是k的倍数,直接煎答案就是2*n/k。否则把前面[n/k]-1个饼先单独直接煎,剩下的k个加上余数个分类讨论,根据和k的关系分为煎3次或者4次。
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
int main()
	LL n, k;  
	cin>>n>>k;
	LL ans=0;
	if(n<=k)
		cout<<2<<"\\n";
		return 0;
	
	
	if(n%k==0)ans = n*2/k;
	else
		ans += 2*((n/k)-1);
		LL t = n-(n/k)*k;
		if(2*t<=k)ans+=3;
		else ans += 4;
	
	cout<<ans<<"\\n";
	return 0;



G.Xor Transformation

链接:https://ac.nowcoder.com/acm/contest/10662/G
来源:牛客网

题目描述
MianKing has one integer XX, he wants to perform some operations to transform XX to YY (Y<X)(Y<X).

In each operation, MianKing can choose one integer 0\\leq A<X0≤A<X and let X=XxorAX=X xor A.

It’s noticed that after an operation, the upper bound of AA will change because XX has changed.

Now you need to help MianKing to find a way to transform XX to YY by doing at most 55 operations.
输入描述:
The first line has two integers X,YX,Y.

1\\leq Y<X\\leq 10^181≤Y<X≤10
18
.
输出描述:
The first line has one integer dd denotes the number of operations you did.

Then there are dd integers A_1…dA
1…d

denotes the AA you choose in each operations.

0\\leq d\\leq 50≤d≤5.
示例1
输入
复制
5 3
输出
复制
3
1 2 5

题意:

  • 给出两个数X和Y(X,Y<1e18),X需要通过小于5次异或一个小于X的数A(A的范围随着X的减少而减小),变得和Y相等,求一种可行的方案(SPJ)。

思路:

  • 比较二进制下X和Y的每一位,如果相同那么不需要异或A来修改,如果不同就需要异或一个1来变成另一个不同的数。
  • 按位比较X和Y,维护一个变量sum,每次遇到不同就更新sum那一位的值为1,如果sum>X了就重新累加。
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
int main()
	LL x,y;
	cin>>x>>y;
	LL xx = x, yy = y;
	vector<LL>ans;
	
	LL cnt = 1, sum = 0;
	while(x>0)
		if(x%2==y%2)
			cnt *= 2;
			x>>=1; y>>=1;
			continue;
		else
			//cout<<sum<<" "<<xx<<"\\n";
			//sum += cnt;
			if(sum+cnt > xx)
				ans.push_back(sum);
				sum = cnt;
			else
				sum += cnt;
			
		
		cnt *= 2;
		x >>= 1;
		y >>= 1;
	
	if(sum>0)ans.push_back(sum);
	cout<<ans.size()<<"\\n";
	for(int i = 0; i < ans.size(); i++)
		if(i!=0)cout<<" ";
		cout<<ans[i];
	
		
	return 0;



C.Stone Game

链接:https://ac.nowcoder.com/acm/contest/10662/C
来源:牛客网

题目描述
MianKing has nn piles of stones and each pile has at most 33 stones, now he wants to merge all of these stones into one pile.

In order to achieve his goal, each time MianKing can choose two piles of stones and merge them into a new pile, and the number of stones in the new pile is the sum of these two piles.

Because it takes manpower to move stones, in each operation if the numbers of these two piles of stones are xx and yy respectively, MianKing should pay (xmod3)(ymod3)(x mod 3)(y mod 3) coins for it.

Now MianKing wants to know the minimum amount of coins he need to pay to merge all of these stones into one pile.

输入描述:
The first line has 33 integers a_1,a_2,a_3a
1

,a
2

,a
3

. And a_ia
i

denotes the number of piles which have ii stones.

0\\leq a_i\\leq 10^90≤a
i

≤10
9

\\sum_i=1^3a_i>0∑
i=1
3

a
i

0
输出描述:
Output one integer: the minimum amount of coins MianKing need to pay for his goal.
示例1
输入
复制
1 1 1
输出
复制
2
示例2
输入
复制
99 66 55
输出
复制
165

题意:

  • 给出n堆石头,含有一块石头的a堆,两块的b堆,三块石头的c堆。合并两堆石头x,y的代价为x*y%3,求合并的最小代价。

思路:

  • 考虑与大小为3的倍数的石头堆合并时代价为零,所以c堆与答案无关,同时贪心的让a和b尽可能多的合并成3的倍数。
  • 首先把a和b等数量的合并(1+2==3,代价只有2),剩余的分两类合并(1+1+1==3,代价3)(2+2+2==6,代价6),最后如果有剩余落单的1就加上合并代价1,落单的2就加4。
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
int main()
	LL a, b, c;
	cin>>a>>b>>c;
	
	LL ans = 0;
	if(a==b)
		ans = a*2;
	else if(a>b)
		ans += b*2;
		LL t = a-b;
		if(t%3==0)
			ans += (t/3)*3;
		else
			ans += (t/3)*3;
			if(t%3==2)
				ans += 1;
		
	else
		ans += a*2;
		LL t = b-a;
		ans += (t/3)*6;
		if(t%3==2)
			ans += 4;
		
	
	cout<<ans<<"\\n";
	return 0;



D.Fight against involution

链接:https://ac.nowcoder.com/acm/contest/10662/D
来源:牛客网

题目描述
MianKing chose a course in this semester. There are nn students in this course, and everyone needs to write a final paper. Let w_iw
i

denote the word count of the i-th student’s final paper.

The i-th student has a lower bound L_iL
i

and an upper bound R_iR
i

on the number of words in his final paper so that L_i\\leq w_i\\leq R_iL
i

≤w
i

≤R
i

The grade rule of this course is very amazing. The grade of the i-th student g_ig
i

is n-K_in−K
i

, K_iK
i

is the number of j \\in [1,n]j∈[1,n] satisfies that w_j>w_iw
j

w
i

.

Every student wants to achieve the highest possible grade, so under the optimal decision w_iw
i

will equal to R_iR
i

for the i-th student.

But MianKing found an interesting thing: let’s assume that \\forall i \\in [1,n], L_i=1000,R_i=10000∀i∈[1,n],L
i

=1000,R
i

=10000. Under the optimal decision w_iw
i

are all equal to 1000010000 and the grades of the students are all nn. But if everyone only writes 1000 words in their final papers, their grades are still all nn and they can use the time they save to play games.

Now to fight against involution, MianKing wants to decide w_iw
i

for each student, and his plan has to satisfy the following conditions:

For each student, his grade cannot be less than that in the original plan.

Minimize the sum of w_iw
i

.

You need help MianKing calculate the minimum value of \\sum_i=1^nw_i∑
i=1
n

w
i

输入描述:
The first line has one integer nn.

Then there are nn lines, the i-th line has two integers L_i,R_iL
i

,R
i

.

1\\leq n\\leq 10^51≤n≤10
5

1\\leq L_i\\leq R_i\\leq 10^91≤L
i

≤R
i

≤10
9

输出描述:
Output the minimum value of \\sum_i=1^nw_i∑
i=1
n

w
i

.
示例1
输入
复制
3
1 10000
1 10000
1 10000
输出
复制
3
示例2
输入
复制
4
1 2
2 2
2 4
3 4
输出
复制
10

题意:

  • 给出n个人写的文章的下限字数和上限字数,成绩为小于等于他字数的总人数(含自己),初始成绩根据上限字数来计算。
  • 现在求在满足每个人成绩不小于初始成绩的情况下(可以等于),修改每个人的字数并让总字数最小,求最小总字数。

思路:

  • 可以发现,对于上限字数相同的文章,因为初始成绩相同,所以修改后的字数也必须相同(否则成绩就会不同),所以只能修改成一样的(即最大下限字数),所以维护对于相同上限字数的文章的最大下限字数和对应的文章数量,则修改后的字数就是最大下限字数乘以文章篇数。
  • 最后枚举的时候再考虑到如果上一篇文章的最大下限字数或者最后选择的字数要大于当前文章的最大下限,那么当前文章的字数必须取最大(可以和上一篇相等,因为成绩只要不小于就行)。
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int inf = 1e10;
map<LL,LL>mm,ma,mi;
set<LL>se;
int main()
	ios::sync_with_stdio(false);  cin.tie(0);
	LL n;  cin>>n;
	for(int i = 1; i <= n; i++)
		LL ai, bi;  cin>>ai>>bi;
		se.insert(bi);
		mm[bi]++;
		if(!ma.count(bi)) ma[bi] = 0;
		ma[bi] = max(ma[bi],ai);
		//if(!mi.count(bi)) mi[bi] = inf;
		//mi[bi] = min(mi[bi],ai);
	
	LL ans = 0, last=0;
	for(LL i : se)
		//ans += max(ma[i],ma[i-1]+1)*mm[i];
		LL t = max(ma[i],max(ma[i-1],last) );
		ans += t*mm[i];
		last = t;
	
	cout<<ans<<"\\n";
	return 0;



A.Matrix Equation

链接:https://ac.nowcoder.com/acm/contest/10662/A
来源:牛客网

题目描述
We call a matrix “01 Square” if and only if it’s a N\\times NN×N matrix and its elements are all 00 or 11.

For two 01 Squares XX,YY, we define two operators X\\times YX×Y and X\\odot YX⊙Y. The value of them are also 01 Square matrices and calculated below(we use ZZ to abbreviate X\\times YX×Y and DD to abbreviate X\\odot YX⊙Y):

Z_i,j=(\\sum_k=1^NX_i,kY_k,j)mod2Z
i,j

=(∑
k=1
N

X
i,k

Y
k,j

) mod 2

D_i,j=X_i,jY_i,jD
i,j

=X
i,j

Y
i,j

Now MianKing has two 01 Squares A,BA,B, he wants to solve the matrix equation below:

A\\times C=B\\odot CA×C=B⊙C

You need to help MainKing solve this problem by calculating how many 01 Squares CC satisfy this equation.

The answer may be very large, so you only need to output the answer module 998244353998244353.

输入描述:
The first line has one integer NN

Then there are NN lines and each line has NN integers, the j-th integer of the i-th line denotes A_i,jA
i,j

Then there are NN lines and each line has NN integers, the j-th integer of the i-th line denotes B_i,jB
i,j

1\\leq N\\leq 2001≤N≤200, A_i,j,B_i,j \\in 0,1A
i,j

,B
i,j

∈0,1

输出描述:
Output the answer module 998244353998244353.
示例1
输入
复制
2
0 1
1 1
1 0
0 1
输出
复制
2
示例2
输入
复制
3
1 0 0
0 1 0
0 0 1
1 1 1
1 1 1
1 1 1
输出
复制
512
示例3
输入
复制
4
0 1 0 1
0 1 1 0
0 1 1 1
1 0 0 1
1 0 1 1
0 1 1 1
1 0 0 1
1 1 1 0
输出
复制
8

题意:

  • 给出两个n*n的01矩阵,A和B
  • 定义两种运算,Z(i,j)=Xi行*Yj列相加%2,D(i,j)=X(i,j)*Y(i,j)
  • 求最多有多少个可能的矩阵C,满足A运算1C==B运算2C。

思路:

  • A和B相同等价于A(i,j)异或B(i,j)为0.
  • Xi行*Yj列相加%2 等价于 Xi行*Yj列相互异或(异或方程组)
  • 高斯消元求线性异或方程组自由元个数即可。

代码:

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int maxn = 255;
const int mod = 998244353;
LL pows(LL x, LL y, LL mod)
	LL res = 1;
	while(y>0)
		if(y&1)res = res*x%mod;
		x = x*x%mod;
		y >>= 1;
	
	return res%mod;


int n, a[maxn][maxn], b[maxn][maxn];
int t[maxn][maxn]; //增广矩阵
int Gauss()
	//用第i个式子消去第i个系数,求得倒三角
	int cnt = 0;//表示行,这样在当前系数全为零时也能继续算下一个系数
	for(int i = 0; i < n; i++)
		int r = cnt;
		while(r<n && !t[r][i])r++;
		if(r==n)continue;
		if(r!=cnt)swap(t[r],t[cnt]);
		
		for(int j = cnt+1; j < n; j++)
			if(t[j][i]!=0)
				for(int k = i; k < n+1; k++)
					t[j][k] ^= t[cnt][k];
			
		
		cnt++;
	
	
	//无解:存在(0,0,...,t)这样的行,且a!=0
	//无穷解:出现(0,0,...,0)这样的行
	int num = 0; //自由元
	for(int i = 0; i < n; i++)
		int ok = 1;
		for(int j = 0; j < n; j++)
			if(t[i][j] != 0)
				ok = 0; break;
			
		
		if(ok==1)
			if(t[i][n]==0)num++;
			if(t[i][n]!=0)return -1;
		
	
	return num;


int main()
	cin>>n;
	for(int i = 0; i < n; i++)
		for(int j = 0; j < n; j++)
			cin>>a[i][j];
	for(int i = 0; i < n; i++)
		for(int j = 0; j < n; j++)
			cin>>b[i][j];
	memcpy(t,a,sizeof(t));
	LL ans = 1;
	for(int i = 0; i < n; i++)
		memcpy(t,a,sizeof(t));
		for(int j = 0; j < n; j++)
			t[j][j] = (a[j][j]-b[j][i]+2)%2;
		int free = Gauss();
		if(free==-1)continue;
		ans = ans*pows(2,free,mod)%mod;
	
	cout<<ans<<"\\n";
	return 0;


以上是关于第 45 届国际大学生程序设计竞赛(ICPC)亚洲区域赛(济南),签到题5题的主要内容,如果未能解决你的问题,请参考以下文章

第 45 届国际大学生程序设计竞赛(ICPC)亚洲区域赛(银川),签到题5题

第 45 届国际大学生程序设计竞赛(ICPC)亚洲区域赛(银川),签到题5题

第 45 届国际大学生程序设计竞赛(ICPC)亚洲区域赛(上海),签到题5题

第 45 届国际大学生程序设计竞赛(ICPC)亚洲区域赛(上海),签到题5题

第 45 届国际大学生程序设计竞赛(ICPC)亚洲区域赛(昆明),签到题4题

第 45 届国际大学生程序设计竞赛(ICPC)亚洲区域赛(昆明),签到题4题