Educational Codeforces Round 13
Educational Codeforces Round 13
A Johny Likes Numbers
做法:假设答案为\(t * k\)考虑$(t - 1) * k $,所以答案显然 为 $ n-n$ \(\%\) $k+k $
代码:
void solve(){
int n, k;
cin >> n >> k;
cout << n - (n % k) + k << endl;
}
B The Same Calendar
做法:考虑对\(7\)取模,闰年\(+2\),平年\(+1\),在考虑答案年和输入的年份是不是同闰同平即可。
代码:
int pd(int n) {
if(n % 400 == 0 || (n % 4 == 0 && n % 100 != 0)) return 1;
return 0;
}
void solve(){
int n;
cin >> n;
int pdq = pd(n);
int now = 365 + pdq;
while(1) {
n++;
if(pd(n)) {
now += 366;
}
else now += 365;
if(now % 7 == 2 && pdq == 1 && pd(n) == 1) break;
if(now % 7 == 1 && pdq == 0 && pd(n) == 0) break;
}
cout << n << endl;
}
C Joty and Chocolate
做法:简单容斥一下即可,答案为:
\[\left \lfloor x / a \right \rfloor * p + \left \lfloor x / b \right \rfloor * q - \left \lfloor x / (lcm(a,b)) \right \rfloor * min(a,b)
\]
代码:
void solve(){
int n , a, b , p , q;
cin >> n >> a >> b >> p >> q;
cout << n / a * p + n / b * q - n /((a * b) / __gcd(a,b)) * min(p , q) << endl;
}
D Iterated Linear Function
做法:两种显然的做法,一个是矩阵快速幂一下,还有也可以直接手拆这个公式去看,其实就是一个等比加一个\(A^{n} * x\),特判\(A == 1\)
代码:
int qmi(int a, int k) {
int res = 1;
while(k) {
if(k & 1) {
res = res * a % mod;
}
k >>= 1;
a = a * a % mod;
}
return res;
}
void solve(){
int a, b,n , x;
cin >> a >> b >> n >> x;
if(a == 1) {
cout << (x + n % mod * b % mod) % mod << endl;
}
else {
int ans = 0;
ans = (qmi(a,n) * x + b * (((qmi(a, n) - 1) % mod + mod) % mod) % mod * qmi(a - 1, mod - 2) % mod) % mod;
cout << ans << endl;
}
}
E Another Sith Tournament
做法:看到数据范围想到状态压缩,比较容易想到的做法是直接考虑二进制每一位,\(1\)表示选手还活着,\(0\)表示选手被淘汰。
这样想了之后,我们可以去想如何去转移胜率的关系,如果将有的1去排列一遍对局情况,复杂度显然不能接受,所以我们可以给状态加一维,所以最后的状态定义为:
\(F_{n,i}\)表示在二进制n的状态下,i为擂主,1号的胜率。
转移方程可以考虑,当前二进制串下,如果出现了多个1,我们考虑这两个人互相击败对方,两种情况,概率相加,这样就是
\[F_{n,j} = max(F_{n,j},P_{j,k} * F_{n - 2^{k},j} + P_{k,j} * F_{n - 2^{j},k})
\]
代码:
void solve(){
int n;
cin >> n;
for (int i = 0;i < n;i ++) {
for (int j = 0;j < n;j ++) {
cin >> p[i][j];
}
}
f[1][0] = 1.0;
for (int i = 2;i < (1 << n);i ++) {
for (int j = 0;j < n;j ++) {
if(i >> j & 1) {
// cout << i << ' ' << j << endl;
for (int k = 0;k < n;k ++) {
if(i >> k & 1) {
f[i][j] = max(f[i][j] , p[j][k] * f[i - (1 << k)][j] + p[k][j] * f[i - (1 << j)][k]);
}
}
}
}
}
if(n == 1) {
printf("%.20lf\n",1.0);
return ;
}
double ans = 0;
// for (int i = 0;i < n;i ++) printf("%.10lf\n", f[(1 << n) - 1][i]);
for (int i = 0;i < n;i ++) ans = max(ans, f[(1 << n) - 1][i]);
printf("%.15lf\n",ans);
}