SCAU2021春季个人排位赛第二场 部分题解

因为是全英题,所以题目的意思都是根据自己的英文水平去理解,可能不是原本的题目意思。望见谅。我英语差点挂科,被捞了。

 

A题

HDU - 4642 

Alice and Bob are playing a kind of special game on an N*M board (N rows, M columns). At the beginning, there are N*M coins in this board with one in each grid and every coin may be upward or downward freely. Then they take turns to choose a rectangle (x1, y1)-(n, m) (1 ≤ x1≤n, 1≤y1≤m) and flips all the coins (upward to downward, downward to upward) in it (i.e. flip all positions (x, y) where x1≤x≤n, y1≤y≤m)). The only restriction is that the top-left corner (i.e. (x1, y1)) must be changing from upward to downward. The game ends when all coins are downward, and the one who cannot play in his (her) turns loses the game. Here's the problem: Who will win the game if both use the best strategy? You can assume that Alice always goes first.

Input

The first line of the date is an integer T, which is the number of the text cases.
Then T cases follow, each case starts with two integers N and M indicate the size of the board. Then goes N line, each line with M integers shows the state of each coin, 1<=N,M<=100. 0 means that this coin is downward in the initial, 1 means that this coin is upward in the initial.

Output

For each case, output the winner’s name, either Alice or Bob.

Sample Input

2
2 2
1 1
1 1
3 3
0 0 0
0 0 0
0 0 0

Sample Output

Alice
Bob

 

题意:将硬币放成n*m的矩阵,1表示朝上,0表示朝下。每次可以选择一个坐标(x,y)使其(x,y)到(n,m)的硬币全部翻个面。Alice先翻动,然后再让Bob翻动。当一个人翻动后全部都为0,也就是硬币全部都向下,那么那个人就赢了,下一个人就输了。现给出目前n*m个硬币的情况,请问在两个人都最优发挥得情况下,谁会获胜?

 

题解:其实刚开始做这道博弈题, 我想到之前做dp的时候做到的博弈dp,然后就在思考会不会也是一个二维dp,但想了想应该没这么难,肯定在某个地方有猫腻。然后因为这是全英题目,我看到“ The only restriction is that the top-left corner (i.e. (x1, y1)) must be changing from upward to downward.”题目的这句话,我以为这道题的核心就是在(1,1)这个点上,然后琢磨了一下,WA掉了。

 

这道题正解其实挺简单,看的不是(1,1)这个点,而是(n,m)这个点。因为不管如何换,(n,m)这个点都会在动。最后肯定都是看(n,m)这个点是否已经被翻,是否已经朝下。如果(n,m)已经是朝下了,那么肯定是要第偶数次翻转才能将其翻回朝下,也就是0。如果是朝上,也就是1,那么就需要奇数次来才能把它翻上去。

代码:

#include <iostream>

using namespace std;

int T;
int n,m;
int f[105][105];
int x[105],y[105];

void read_in()
{
    cin>>n>>m;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
          cin>>f[i][j];
}

void work()
{
    if(f[n][m])
      cout<<"Alice\n";
    else
      cout<<"Bob\n";
}

int main()
{
    ios::sync_with_stdio(false),cin.tie(0);
    cin>>T;
    while(T--)
    {
        read_in();
        work();
    }
    return 0;
}

 

C题

LightOJ - 1248

 

Given a dice with n sides, you have to find the expected number of times you have to throw that dice to see all its faces at least once. Assume that the dice is fair, that means when you throw the dice, the probability of occurring any face is equal.

For example, for a fair two sided coin, the result is 3. Because when you first throw the coin, you will definitely see a new face. If you throw the coin again, the chance of getting the opposite side is 0.5, and the chance of getting the same side is 0.5. So, the result is

1 + (1 + 0.5 * (1 + 0.5 * …))

= 2 + 0.5 + 0.52 + 0.53 + …

= 2 + 1 = 3

Input

Input starts with an integer T (≤ 100), denoting the number of test cases.

Each case starts with a line containing an integer n (1 ≤ n ≤ 105).

Output

For each case, print the case number and the expected number of times you have to throw the dice to see all its faces at least once. Errors less than 10-6 will be ignored.

Sample Input

5
1
2
3
6
100

Sample Output

Case 1: 1
Case 2: 3
Case 3: 5.5
Case 4: 14.7
Case 5: 518.7377517640

 

 

题意:一个n面体,像丢骰子一样投,请问每个面至少出现一次的话预期(期望)要投多少次?

 

题解:当时比赛时一直没有思路,以为很难。之后看榜发现挺多人做了,就回来推了推这道题。

假设以3面体,第一投绝对是新的一面,ans=1。

投第二次,有 \frac{1}{3} 的可能是原本投过的,有  \frac{2}{3} 可能是新的一面,然后根据先前推的2面体的例子,ans=1+(1/3 * ( 1 + 1/3 * …… + 2/3 * ……) + 2/3 * (  1 + 1/3 * (…… + 1/3 * ……

最后然后我就试出了  ans= n+ \sum_{i=1}^{n} \frac{i}{n-i},就得到答案了。

 

正确的理解是,每期待第n个新面是,投出新面的概率为 \frac{n-i+1}{n},而期望值就为n * \sum_{i=1}^{n} \frac{n-i+1}{n}

 

代码:

#include <iostream>
#include <stdio.h>

using namespace std;

int main()
{
    int T;
    cin>>T;
    for(int Ti=1;Ti<=T;Ti++)
    {
        double n,ans;
        cin>>n;
        ans=n;
        for(double i=1;i<n;i++)
            ans+=i/(n-i);
        cout<<"Case "<<Ti<<": ";
        printf("%.6lf\n",ans);
    }
    return 0;
}

 

 

D题

 LightOJ - 1138 

You task is to find minimal natural number N, so that N! contains exactly Q zeroes on the trail in decimal notation. As you know N! = 1 * 2 * ... * N. For example, 5! = 120, 120 contains one zero on the trail.

Input

Input starts with an integer T (≤ 10000), denoting the number of test cases.

Each case contains an integer Q (1 ≤ Q ≤ 108) in a line.

Output

For each case, print the case number and N. If no solution is found then print impossible.

Sample Input

3
1
2
5

Sample Output

Case 1: 5
Case 2: 10
Case 3: impossible

 

题意:含有Q个后缀0的 N!的最小N是多少。

 

题解:很明显,在N!中,2的个数很多很多,所以只要看5的个数即可。

一开始我就想着,能不能打个1e8的表,但是爆空间了hh。然后后面就没想这道题了。

 

这道题的正解是二分查找。

直接找N,如果mid!的后缀0大于或等于q,则往前找,否则往后找。

 

注意:二分开始前的上界记得开大点!改题时WA了很多次!

 

代码:

#include <iostream>

using namespace std;

int get_(int k)
{
	int sum=0;
	while(k)
	{
		sum+=k/5;
		k=k/5;
	}
	return sum;
}

int main()
{

    int T;
    cin>>T;
    for(int i=1;i<=T;i++)
    {
        int q,ans=-1;
        cin>>q;
        int l=1,r=10000000000;
        while(l<=r)
        {
        	int mid=(l+r)/2;
        	int cnt=get_(mid);
        	if(cnt==q)
        	{
        		ans=mid;
        		r=mid-1;
			}
			else
			if(cnt>q)
			  r=mid-1;
			else
			  l=mid+1;
		}
		if(ans==-1)
      	  cout<<"Case "<<i<<": "<<"impossible\n";
      	else
      	  cout<<"Case "<<i<<": "<<ans<<'\n';
    }
    
    return 0;
}

 

 

E题

 CodeForces - 915C

 

You are given two positive integer numbers a and b. Permute (change order) of the digits of a to construct maximal number not exceeding b. No number in input and/or output can start with the digit 0.

It is allowed to leave a as it is.

Input

The first line contains integer a (1 ≤ a ≤ 1018). The second line contains integer b (1 ≤ b ≤ 1018). Numbers don't have leading zeroes. It is guaranteed that answer exists.

Output

Print the maximum possible number that is a permutation of digits of a and is not greater than b. The answer can't have any leading zeroes. It is guaranteed that the answer exists.

The number in the output should have exactly the same length as number a. It should be a permutation of digits of a.

Examples

Input

123
222

Output

213

Input

3921
10000

Output

9321

Input

4940
5000

Output

4940

 

题意:用a字符串里的数字组成的不大于b的最大值为多少。

 

题解:题目保证一定有解。

当a的位数小于b时,直接凑最大就是正解。

当a和b的位数相同时,看题目,数据量挺小的,DFS就能够跑完。

但是DFS可以剪枝一下,a前半部分取的数只能够等于b,当a选到一个数,在这一位上是小于b的,那么后面的a都可以从0-9里面随便选了。所以每次取数字时判断一下即可。

 

代码:

#include <iostream>
#include <stdio.h>

using namespace std;

int main()
{
    int T;
    cin>>T;
    for(int Ti=1;Ti<=T;Ti++)
    {
        double n,ans;
        cin>>n;
        ans=n;
        for(double i=1;i<n;i++)
            ans+=i/(n-i);
        cout<<"Case "<<Ti<<": ";
        printf("%.6lf\n",ans);
    }
    return 0;
}

 

G题

 SGU - 533 

 

 

Polycarp loves not only to play games, but to invent ones as well. He has recently been presented with a board game which also had lots of dice. Polycarp quickly noticed an interesting phenomenon: the sum of dots on any two opposite sides equals 7.
 


The dice


An unfolded die

Polycarp invented the following game. He asks somebody to tell a positive integer n and then he constructs a dice tower putting the dice one on another one. A tower is constructed like that: Polycarp puts a die on the table and then (if he wants) he adds more dice, each time stacking a new die on the top of the tower. The dice in the tower are aligned by their edges so that they form a perfect rectangular parallelepiped. The parallelepiped's height equals the number of dice in the tower and two other dimensions equal 1 (if we accept that a die's side is equal to 1).
 


An example of a tower whose height equals 3

Polycarp's aim is to build a tower of minimum height given that the sum of points on all its outer surface should equal the given number n (outer surface: the side surface, the top and bottom faces).

Write a program that would determine the minimum number of dice in the required tower by the given number n. Polycarp can construct any towers whose height equals 1 or more.
 

Input

The only input line contains integer n (1 ≤ n ≤ 106).
 

Output

Print the only integer — the number of dice in the required tower. If no such tower exists, print 

-1

.
 

Example(s)

sample input
sample output
50
3

 

sample input
sample output
7
-1

 

sample input
sample output
32
2

 

题意:这题老长了,看英文看得头疼。

就是叠骰子,正着叠,裸露在外(四周+顶+底)的面的点数相加的和能达到n的最小骰子数是多少。

 

题解:可以看出,骰子横着的4个数之和都为14,那么对于一个2个以上骰子叠起来只需要看顶部的值和底部的值即可。

但是这里要记得特判只有1个骰子的情况。1个骰子只能够加成21点,而2个骰子最小只能加成30点,特判这两种情况即可完美解决。

 

代码:

#include <iostream>

using namespace std;

int n;
int main()
{
	cin>>n;
    if(n<21)
      cout<<-1;
    else
    {
        int h=n/14,k=n%14;
        if(k<2 || k>12 || (h==1 && n!=21))
          cout<<-1;
        else
          cout<<h;
    }


    return 0;
}

 

 

 

 

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值