A. Johny Likes Numbers(Codeforces 678A)
思路
首先直接枚举
k
的倍数是不可能的,数据规模告诉我们必须通过直接计算得到结果。下面分类,当
代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll n, k, tmp;
int main() {
cin >> n >> k;
tmp = n % k;
if(tmp == 0) {
cout << n + k << endl;
}
else {
cout << n - tmp + k << endl;
}
return 0;
}
B. The Same Calendar(Codeforces 678B)
思路
首先想象下面的场景,我们将今年的每月分的日历拼接起来形成年历,然后将从今年开始后的 4000 年的年历拼接起来形成一份超长的年历。因为 365mod7=2 ,所以根据那份超长的日历,若今年是平年且今年的第一天为周一,那么明年的第一天为周二,若今年是闰年且今年的第一天为周一,那么明年的第一天为周三。所以我们当我们一年一年这样算下去,碰到某年的第一天为周一且该年的“润性”与今年一致时,该年的日历就和今年是一致的。
代码
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e6;
int n, cur, ans, init;
bool isLeap(int x) {
if(x % 400 == 0) {
return true;
}
if(x % 4 == 0) {
return x % 100;
}
return false;
}
int main() {
cin >> n;
cur = 0;
init = isLeap(n);
for(int i = n + 1; i < maxn; i++) {
if(isLeap(i - 1) == false) {
cur = (cur + 1) % 7;
}
else {
cur = (cur + 2) % 7;
}
if(cur == 0 && isLeap(i) == init) {
ans = i;
break;
}
}
cout << ans << endl;
return 0;
}
C. Joty and Chocolate(Codeforces 678C)
思路
只能被
a
整除的编号的瓦
代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll n, a, b, p, q, da, db, dc, ans;
ll lcm(ll a, ll b) {
return a / __gcd(a, b) * b;
}
int main() {
cin >> n >> a >> b >> p >> q;
da = n / a;
db = n / b;
dc = n / lcm(a, b);
ans = p * (da - dc) + q * (db - dc) + max(p, q) * dc;
cout << ans << endl;
return 0;
}
D. Iterated Linear Function(Codeforces 678D)
思路
题目的意思就是求当
a0=x,an=Aan−1+B
时的
an
,这里相当于
a0
进行了
n
次线性变换,对于这种
代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod = 1e9 + 7;
ll a, b, n, x;
struct matrix {
int n, m;
ll a[2][2];
matrix(int n = 2, int m = 2): n(n), m(m) {
memset(a, 0, sizeof(a));
}
matrix mod_mul(matrix &b, ll mod) const {
matrix tmp(n, b.m);
for(int i = 0; i < n; i++) {
for(int j = 0; j < b.m; j++) {
for(int k = 0; k < m; k++) {
tmp.a[i][j] = (tmp.a[i][j] + a[i][k] * b.a[k][j] % mod) % mod;
}
}
}
return tmp;
}
matrix mod_pow(ll nn, ll mod) const {
matrix a = *this, tmp(n, n);
for(int i = 0; i < n; i++) {
tmp.a[i][i] = 1;
}
for(; nn > 0; nn >>= 1) {
if(nn & 1) {
tmp = tmp.mod_mul(a, mod);
}
a = a.mod_mul(a, mod);
}
return tmp;
}
}mat, ans;
int main() {
cin >> a >> b >> n >> x;
mat.a[0][0] = a;
mat.a[0][1] = b;
mat.a[1][0] = 0;
mat.a[1][1] = 1;
ans = mat.mod_pow(n, mod);
cout << (x * ans.a[0][0] + ans.a[0][1]) % mod << endl;
return 0;
}
E. Another Sith Tournament(Codeforces 678E)
思路
最朴素的想法是枚举人物出场顺序,然后就能算出主人公获胜的概率。然而这样的想法是不可行的。因为阶乘复杂度是本题无法承受的。怎么办呢?按照经验,这种数据规模较小的朴素思想为枚举排列的题目可以通过状态压缩的集合表示问题解决过程中的阶段,从而记录最优子结构,使问题能通过动态规划的思想得以解决。假设我们用将变量i表示当前阶段,其二进制形式表示当前哪些人已经死了(
0
),哪些人还活着(
代码
#include <bits/stdc++.h>
using namespace std;
const int maxn = 18;
int n, x, y, ub;
double tmp, ans, p[maxn][maxn], d[1<<maxn][maxn];
int main() {
scanf("%d", &n);
for(int i = 0; i < n; i++) {
for(int j = 0; j < n; j++) {
scanf("%lf", &p[i][j]);
}
}
ub = 1 << n;
d[1][0] = 1.0;
for(int i = 2; i < ub; i++) {
for(int j = 0; j < n; j++) {
x = 1 << j;
if(i & x == 0) {
continue;
}
for(int k = 0; k < n; k++) {
y = 1 << k;
if(i & y == 0) {
continue;
}
tmp = p[j][k] * d[i^y][j] + p[k][j] * d[i^x][k];
d[i][j] = max(d[i][j], tmp);
}
}
}
for(int j = 0; j < n; j++) {
ans = max(ans, d[ub-1][j]);
}
printf("%.10f\n", ans);
return 0;
}
(其他题目略)