第一题
题意
一堆石子共N颗,两人(niu和yang)轮流取石子,规则是每次取 4i(i为非负整数) 颗,直到轮到的人不能取则为输。两个人都是聪明人。给出N,求赢家名字。
思路
明显是博弈题,SG函数解决,先打表找规律。
b[i]
用来实现mex函数的辅助数组
sg[i]
i的sg值
dp[i]
4i
for(int x = 1;x < 1000;x++) {
memset(b, false, sizeof(b));
for(int i = 0;i < 16;i++) if(x-dp[i] >= 0)
b[sg[x-dp[i]]] = true;
for(int i = 0;i < 1000;i++) if(!b[i]) {
sg[x] = i;
break;
}
}
得到明显的规律
i | sg(i) |
---|---|
0 | 0 |
1 | 1 |
2 | 0 |
3 | 1 |
4 | 2 |
5 | 0 |
6 | 1 |
7 | 0 |
8 | 1 |
9 | 2 |
sg值周期性循环出现。必败态为 i%5==0或2
代码
#include <iostream>
using namespace std;
int main() {
int t;
cin >> t;
while(t--) {
int n;
cin >> n;
if(n % 5 == 0 || n % 5 == 2)
cout << "yang" << endl;
else
cout << "niu" << endl;
}
return 0;
}
第二题
题意
给出长为N的整数序列,连续的子串里最大值和次大值异或和最大是多少?
思路
不会
第三题
题意
有n+m个人,n个人是A属性,m个人是B属性。每次取出n+m个人里的2个人,其中具有B属性的会改为A属性。问所有人都变为A属性需要取的次数的期望。
思路
令 dp(n,m) 为需要取的次数的期望。则取一次以后可以到达的状态为 (n,m),(n+1,m−1),(n+2,m−2) 。所有可能的种数为 S=(n+m)(n+m−1)2
编号i | 状态 | 可能的种数 Ci |
---|---|---|
1 | (n,m) | n(n-1)/2 |
2 | (n+1,m-1) | nm |
3 | (n+2,m-2) | m(m-1)/2 |
dp(n,m)=⎧⎩⎨⎪⎪⎪⎪C1S(1+dp(n,m))+C2S(1+dp(n+1,m−1))+C3S(1+dp(n+2,m−2))C1S(1+dp(n,m))+C2S(1+dp(n+1,m−1))0m>1m=1m=0
因此可以让m=0开始递增解出 dp(n,m)
代码
#include <bits/stdc++.h>
using namespace std;
double solve(int n, int m, double y, double z) {
double sum1, sum2;
sum1 = 1.0 * n * m * (1 + y);
sum2 = m >= 2? 1.0 * m * (m-1) / 2 * (1+z) : 0;
return (sum1 + sum2 + n*(n-1)/2.0) / ((n+m-1)*(n+m)/2.0-n*(n-1)/2);
}
int main() {
double x, y=0, z = 0;
int n, m;
scanf("%d%d", &n, &m);
for(int i = 1;i <= m;i++) {
x = solve(n+m-i, i, y, z);
y = x;
z = y;
}
printf("%.1f\n", x);
return 0;
}