A - Lucky 7
大水题,模拟即可。
#include <iostream>
#include <cstdio>
using namespace std;
int main() {
string s;
cin >> s;
if (s[0] == '7' || s[1] == '7' || s[2] == '7') {
puts("Yes");
} else {
puts("No");
}
return 0;
}
B - FizzBuzz Sum
还是大水题,模拟。
#include <iostream>
#include <cstdio>
using namespace std;
int main() {
int n;
long long ans = 0;
cin >> n;
for (int i = 1; i <= n; i++) {
if (i % 3 != 0 && i % 5 != 0) {
ans += i;
}
}
cout << ans;
return 0;
}
C - Sum of gcd of Tuples (Easy)
这次的前几题怎么都那么水鸭。
数据范围那么小,暴力枚举即可。
#include <iostream>
#include <cstdio>
using namespace std;
int k;
long long ans;
int gcd(int a, int b) {
if (b == 0) return a;
return gcd(b, a % b);
}
int main() {
cin >> k;
for (int a = 1; a <= k; a++) {
for (int b = 1; b <= k; b++) {
int d = gcd(a, b), e;
for (int c = 1; c <= k; c++) {
e = gcd(d, c);
ans += e;
}
}
}
cout << ans;
return 0;
}
D - RGB Triplets
枚举前两个数的位置,假设是i,j(\(i < j\))
处理一个后缀颜色数量cnt[x][c]代表从x-n有多少颜色c。
枚举的时候先加上cnt[j+1][除了i,j的另外一种颜色]
然后再判断和i到j等距的那个点有没有被算上,如果被算上了直接减一即可。
#include <iostream>
#include <cstdio>
using namespace std;
long long n;
char s[4010];
long long cnt[4010][3];//0:R 1:G 2:B
long long ans;
long long f(char c) {
if (c == 'R') return 0;
if (c == 'G') return 1;
return 2;
}
long long g(char a, char b) {
return (3 - f(a) - f(b)) % 3;
}
int main() {
scanf("%lld%s", &n, s + 1);
for (long long i = n; i >= 1; i--) {
cnt[i][0] = cnt[i + 1][0];
cnt[i][1] = cnt[i + 1][1];
cnt[i][2] = cnt[i + 1][2];
cnt[i][f(s[i])]++;
}
for (long long i = 1; i < n - 1; i++) {
for (long long j = i + 1; j < n; j++) {
if (s[i] == s[j]) continue;
ans += cnt[j + 1][g(s[i], s[j])];
if (j + j - i <= n && f(s[j + j - i]) == g(s[i], s[j])) ans--;
}
}
cout << ans;
return 0;
}
E - Sum of gcd of Tuples (Hard)
简单容斥。
设dp[d]=gcd(a1,a2...an)=d的数列的数量,显然ai得是d的倍数,有\(\frac{k}{d}\)种选择,所以有\({\frac{k}{d}}^n\)个数列。
但是这样会包含gcd=d2,gcd=d3...的答案,所以要减去。
实现的时候倒着循环即可。
#include <iostream>
#include <cstdio>
using namespace std;
const long long mod = 1e9 + 7;
long long n, k;
long long dp[100010], ans;
long long ksm(long long a, long long b) {
long long ret = 1;
while (b) {
if (b & 1) {
ret = (ret * a) % mod;
}
a = (a * a) % mod;
b >>= 1;
}
return ret;
}
int main() {
cin >> n >> k;
for (long long i = k; i >= 1; i--) {
long long num = k / i;
dp[i] = ksm(num, n);
for (long long j = i + i; j <= k; j += i) {
dp[i] = (dp[i] - dp[j] + mod) % mod;
}
ans = (ans + dp[i] * i) % mod;
}
cout << ans;
return 0;
}
F - Select Half
设计子状态 \(dp[i]\) 代表前 \(i\) 个数取 \(\frac{i}{2}\) 个数的最大值,显然 \(dp[1]=0\)。
若 \(i\) 为奇数
则若不选 \(i\),答案是 \(dp[i-1]\),若选 \(i\),答案是 \(dp[i-2]+a[i]\),在两者之间取 \(\max\) 即可
若 \(i\) 为偶数,若选 \(i\) 同上,若不选 \(i\) 只有取 \(i-1\) 以内左右编号为奇数的数这一种情况,两者取 \(\max\) 即可。
#include <iostream>
#include <cstdio>
using namespace std;
long long n;
long long a[200010];
long long dp[200010];
long long sum[200010];
int main() {
scanf("%lld", &n);
for (long long i = 1; i <= n; i++) scanf("%lld", &a[i]);
sum[1] = a[1];
for (long long i = 3; i <= n; i += 2) {
sum[i] = sum[i - 2] + a[i];
}
for (long long i = 2; i <= n; i++) {
if (i & 1) {
dp[i] = max(dp[i - 1], dp[i - 2] + a[i]);
} else {
dp[i] = max(sum[i - 1], dp[i - 2] + a[i]);
}
}
printf("%lld", dp[n]);
return 0;
}
标签:AtCoder,cnt,return,Beginner,int,long,dp,include,162
From: https://www.cnblogs.com/zcr-blog/p/17067114.html