2022“杭电杯”中国大学生算法设计超级联赛签到题5题

Posted 小哈里

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2022“杭电杯”中国大学生算法设计超级联赛签到题5题相关的知识,希望对你有一定的参考价值。

Solved Problem ID Title Ratio (Accepted / Submitted)
1001 Bowling 7.63% (18/236)
1002 Independent Feedback Vertex Set 42.38% (189/446)
1003 Counting Stickmen 23.06% (463/2008)
1004 Black Magic 35.71% (886/2481)
1005 Cyber Painter 16.67% (9/54)
1006 Sumire 22.67% (221/975)
1007 Weighted Beautiful Tree 21.99% (84/382)
1008 Triangle Game 23.25% (600/2581)
1009 Counting Good Arrays 13.73% (84/612)
1010 Connectivity of Erdős-Rényi Graph 39.37% (50/127)
1011 Rock Tree 8.52% (15/176)

文章目录

4.Black Magic

Black Magic
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 524288/524288 K (Java/Others)
Total Submission(s): 39 Accepted Submission(s): 17

Problem Description
HoshiYo is learning Black Magic with n blocks. The left and right sides of each block are painted black or white. HoshiYo arranges the blocks in a row in a certain order without rotating them and then releases the Black Magic. Here’s what happens next:
For any two adjacent blocks, if the right side of the left block and the left side of the right block are both painted black, then the two sides will be pasted together making the two blocks into one.
HoshiYo wants to know the minimum and maximum blocks he can get after releasing the Black Magic.

Input
The first line contains an integer T (1≤T≤4×103), indicating the number of test cases.

Each test case contains four integers E,L,R,B (0≤E,L,R,B≤105,E+L+R+B≥1), indicating the number of blocks.
E: the number of blocks whose both sides are painted white.
L: the number of blocks whose left side is painted black and right side is painted white.
R: the number of blocks whose right side is painted black and left side is painted white.
B: the number of blocks whose both sides are painted black.
It guaranteed that the sum of E+L+R+B over all test cases won’t exceed 106.

Output
For each test case, output two integers in a single line, indicating the minimum and maximum blocks HoshiYo can get.

Sample Input
3
1 1 1 1
1 2 3 4
3 4 5 6

Sample Output
2 4
4 8
8 16

Hint
Let’s denote a block by (x,y), where x indicates the color on the left side, and y indicates the color on the right side. We use 0 to represent white and 1 to represent black.

For the first test case in the sample, here is a possible solution to get the minimum number of blocks:

(0,0)(0,1)(1,1)(1,0)

As shown above, the last three blocks will be pasted into one.

And here is a possible solution to get the maximum number of blocks:

(0,0)(1,0)(1,1)(0,1)

As shown above, any two blocks will not be pasted together.

Source
2022“杭电杯”中国大学生算法设计超级联赛(7)

题意:

  • 给出 n 个方块,每个方块的左/右都可能是黑或白(共四种)。
  • 将这些方块排成一列,如果两个相邻方块相连接的面都是黑色,那么这两个方块会连在一起。
  • 求连通块的最大/最小数量

思路:

  • 分类讨论即可,最小就让01 11 10合并成一整块的尽可能多,最大就让10 11 01 分成三块的尽可能多。
  • 注意边界的判断,即某些块没有的样例情况下。如以下数据:
    5
    1 1 1 1
    0 1 1 1
    1 0 0 1
    1 1 1 0
    0 0 0 1
    2 4
    1 3
    2 2
    2 3
    1 1
//1004
#include<bits/stdc++.h>
using namespace std;
#define ios ios::sync_with_stdio(0), cin.tie(0),cout.tie(0)
typedef long long LL;
int main()
	IOS;
	LL T;  cin>>T;
    while(T--)
		LL E, L, R, B;
		cin>>E>>L>>R>>B;
		LL a = E, b = L, c = R, d = B;
		//最小
		if(d>0)d = 1;                 //11 11 11 合并成11
		if(b>0 || c>0)d = 0;          //01 11 合并成01
		LL t = min(b,c);              //01 10 合并成00
		b -= t;  c-=t;  a += t;       //00++
		LL mi = a+b+c+d;
		//最大
		a = E, b = L, c = R, d = B;
		t = min(a,d);				  //00 11 合并为 01(答案+t)
		a -= t;  d -= t;  c += t;     //01++
		LL mx = t+b+c;	   			  //10 10 10 01 01 01 (d的块数+1, 答案+b+c)
		if(a>0) mx += a;
		if(d>0) mx++;                 //10 10 (11) 01 01 中间可以放一块
		cout<<mi<<" "<<mx<<"\\n";
	
    return 0;



8.Triangle Game

Triangle Game
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 524288/524288 K (Java/Others)
Total Submission(s): 51 Accepted Submission(s): 37

Problem Description
Kate and Emilico are playing a game. There are 3 integers a,b,c. It is guaranteed that there exists a non-degenerate triangle whose side lengths are a,b,c respectively. The game goes as follows. Players take turns in decreasing a certain positive integer on one of the 3 integers. If there doesn’t exist a non-degenerate triangle whose side lengths are a,b,c after a player’s operation, the player loses.

Kate goes first. If both of them play optimally, will Kate win?

Input
The first line of input contains one integer T (1≤T≤104), indicating the number of test cases.

For each test case, the only line contains 3 integers a,b,c (1≤a,b,c≤109). It is guaranteed that there exists a non-degenerate triangle whose side lengths are a,b,c respectively.

Output
For each test case, if Kate will win, output Win in a single line. Otherwise, output Lose in a single line.

Sample Input
3
2 2 3
2 3 4
5 3 4

Sample Output
Win
Lose
Win

Source
2022“杭电杯”中国大学生算法设计超级联赛(7)

题意:

  • 给出一个三角形,三边边长分别为 a,b,c。 现 Kate 和 Emilico 二人做游戏,每轮需要令三角形的一边长度减去一正整数,使这个三角形退化的一方输。
  • Kate 先手,双方均采用最优策略,问 Kate 是否会获胜。

思路:

  • 结论是:Kate 获胜当且仅当 (a-1)^(b-1)^(c-1)!=0。
    值得一提的是,这个结论与上一把牛客7的 K. Great Party 题是一样的。
  • 官方证明:
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
int main()
    int T;  cin>>T;
    while(T--)
        LL a, b, c;  cin>>a>>b>>c;
        a--; b--; c--;
        if((a^b^c)==0)cout<<"Lose\\n";
        else cout<<"Win\\n";
    
    return 0;

3.Counting Stickmen

Counting Stickmen
Time Limit: 18000/9000 MS (Java/Others) Memory Limit: 524288/524288 K (Java/Others)
Total Submission(s): 84 Accepted Submission(s): 30

Problem Description
Namesolo has fallen in love with the game Stick Fight. But when he is playing the game, he wonders how to find out the number of stickmen in the game.

In this question, we define the stick man as shown in the picture above. It has a chain of length 1 as the head, two chains of length 2 as the arms, a chain of length 1 as the body, and two chains of length 1 as the legs. For example, the red part in this picture can be viewed as a stick man, with chain (2,3) to be the head, chains (3,4,6) and (3,9,10) to be the arms, chain (3,5) to be the body, and chains (5,7) and (5,8) to be the legs.

The game can be viewed as a tree, and Namesolo wants to know how many stickmen are there. Please note that two stickmen are different when there is at least one different edge between the two edge sets that make up the two stickmen.

Because the answer may be too large, Namesolo wants to know the answer modulo 998244353.

Input
The first line of input contains one integer T (1≤T≤15), indicating the number of test cases.

For each test case, the first line contains an integer n (1≤n≤5×105), indicating the number of vertices in the tree. Each of the following n−1 lines contains two integers a,b (1≤a,b≤n), indicating that there is an edge connecting a and b in the tree.

It is guaranteed that the sum of n over all cases won’t exceed 3×106.

Output
For each test case, output an integer representing the answer modulo 998244353.

Sample Input
1
9
1 2
2 3
3 4
2 5
5 6
2 7
7 8
7 9

Sample Output
1

Source
2022“杭电杯”中国大学生算法设计超级联赛(7)

题意:

  • 给出一棵n(5e5)个点的树,判断其中有多少个火柴人(2手臂,2手掌,身体,2腿,共8条边),输出数量%998244353。

思路:

  • 首先枚举每个点作为身体,然后往外拓展一层 ,可以得到他儿子的信息,根据子树大小分别为0,1,>2的分成三类(0只能做头,1只能做头和手, >2都可以)。
  • 然后我们对于当前点u为身体下脚的可能性(肯定是>2的点),那么脚的可选方案数就是C(x,2)。
    然后对于这个脚,我们可以选0或1作为头,也可以选剩下的2作为头,总共分为3大类。
    对于这3大类,再对两只手分类(手=1+1, 或=1+2,或者=2+2)。
    总共就是9类。
  • 对于每一类按照脚的方案数x头的方案数x手的方案数,用乘法原理算出结果,最后累加即可。
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const LL maxn = 5e5+10, mod = 998244353;
#define IOS ios::sync_with_stdio(0), cin.tie(0),cout.tie(0)

LL pows(LL a, LL x)  if(x==0)return 1; LL t = pows(a, x>>1); if(x%2==0)return t*t%mod; return t*t%mod*a%mod; 
LL pows(LL a, LL x, LL p)  if(x==0)return 1; LL t = pows(a, x>>1, p); if(x%2==0)return t*t%p; return t*t%p*a%p; 
LL exgcd(LL a, LL b, LL &x, LL &y) if(!b) x = 1, y = 0; return a; elseLL r = exgcd(b, a%b, x, y); LL t = x; x = y; y = t-a/b*y; return r; 
void exgcd(LL a, LL b, LL &d, LL &x,  LL & y, LL MOD)  if (b==0)  d = a; x = 1; y = 0;  else  exgcd(b, a % b, d, y, x, MOD); y -= x * (a / b);  
LL inv(LL a, LL MOD)  LL d=0, x=0, y=0; exgcd(a, MOD,  d,  x, y, MOD); return d == 1 ? (x + MOD) % MOD : -1; 

LL fac[maxn], inv2[maxn];
LL mpow(LL a, LL x) 
	if(x==0)return 1;
	LL t = mpow(a, x>>1);
	if(x%2==0)return t*t%mod;
	return t*t%mod*a%mod;

LL init()
	fac[0]=inv2[0]=1;
	for(LL i = 1; i < maxn; i++)
		fac[i]=fac[i-1]*i%mod; inv2[i]=mpow(fac[i],mod-2);
	return 0;

LL C(LL x, LL y) 
	if(y<0 || y>x)return 0;
	return fac[x]*inv2[y]%mod*inv2[x-y]%mod;


vector<LL>G[maxn];

int main()
    IOS;
    init();
    LL T;  cin>>T;
    while(T--)
        LL n;  cin>>n;
        for(int i = 1; i <= n; i++)G[i].clear();
        for(LL i = 1; i < n; i++)
            LL u, v;  cin>>u>>v;
            G[u].push_back(v);
            G[v].push_back(u);
        
        LL ans = 0;
        for(LL i = 1; i <= n; i++)
            LL a = 0, b = 0, c = 0; //子树大小分别为0,1,>2
            vector<LL>vc;
            LL sum = 0;
            //a只能做头,b只能做头和手, c都可以
            for(LL v : G[i])
                if(G[v].size()==1)a++;
                else if(G[v].size()==2)b++;
                else 
                    c++;
                    vc.push_back(G[v].size());
                    sum = (sum+G[v].size()-1)%mod;
                
            
            LL res = 0;
            LL sum2 = 0; //所有脚作为手的可能性
            for(auto x : vc) 
                x--;
                sum2 = (sum2+(sum-x)*x%mod+mod)%mod; 
            
            sum2 = sum2*inv(2,mod)%mod;
            //选脚作为脚(必须)
            for(auto x : vc)
                x = x-1;
                LL sum3 = (sum2-x*(sum-x)%mod+mod)%mod; //去掉了x的所有脚x脚
                //res += 脚x头x手
                //选头作为头
                if(c>=3 && a>=1)res = (res+C(x,2)*a%mod*sum3%mod)%mod;    //手=脚+脚
                if(c>=2 && a>=1 && b>=1)res = (res+C(x,2)*a%mod*((sum-x)%mod*b)%mod)%mod ; //手=脚+手
                if(c>=1 && a>=1 && b>=2)res = (res+C(x,2)*a%mod*C(b,2)%mod)%mod;  //手=手+手
                //选手作为头
                if(c>=3 && b>=1)res = (res+C(x,2)*b%mod*(sum3)%mod)%mod;       //手=脚+脚
                if(c>=2 && b>=2)res = (res+C(x,2)*b%mod*(sum-x)%mod*(b-1)%mod)%mod;       //手=脚+手
                if(c>=1 && b>=3)res = (res+C(x,2)*b%mod*C(b-1,2)%mod)%mod;       //手=手+手
                //选脚作为头
                if(c>=4)res = (res+C(x,2)*(c-3)%mod*sum3%mod)%mod;       //手=脚+脚
                if(c>=3 && b>=1)res = (res+C(x,2)*(c-2)%mod*((sum-x)*b%mod)%mod)%mod;       //手=脚+手
                if(c>=2 && b>=2)res = (res+C(x,2)*(c-1)%mod*C(b,2)%mod)%mod;       //手=手+手
            
            ans = (ans+res+mod)%mod;
        
        cout<<(ans+mod)%mod<<'\\n';
    
    return 0;



几组非样例的数据:

2
9
1 2
2 3
3 4
2 5
5 6
2 7
7 8
7 9
11 
1 2
2 3
2 11
3 4
3 5
3 9
4 6
5 7
5 8
9 10
1
10

1
13
1 2
2 3
2 11
3 4
3 5
3 9
4 6
5 7
5 8
9 10
4 12
9 13
48

1
15
1 2
2 3
2 11
3 4
3 5
3 9
4 6
5 7
5 8
9 10
4 12
9 13
3 14
14 15
144


  • 官方题解如下:
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const LL maxn = 1e7+10, mod = 998244353;
#define IOS ios::sync_with_stdio(0), cin.tie(0),cout.tie(0)

vector<LL>G[maxn];
LL s0[maxn], s1[maxn], s2[maxn];
LL C(LL x, LL y) return x*(x-1)/2%mod; // C(x,2)

int main()
    IOS;
    LL T;  cin>>T;
    while(T--)
        LL n;  cin>>n;
        for(int i = 1; i 2022“杭电杯”中国大学生算法设计超级联赛签到题5题

2022“杭电杯”中国大学生算法设计超级联赛签到题4题

2022“杭电杯”中国大学生算法设计超级联赛签到题3题

2022“杭电杯”中国大学生算法设计超级联赛签到题5题

2022“杭电杯”中国大学生算法设计超级联赛签到题5题

2022“杭电杯”中国大学生算法设计超级联赛签到题5题