传送门:http://codeforces.com/contest/755
A题题意是给你一个数字n,让你找到一个数字m,使得n*m+1为合数,范围比较小,直接线性筛出1e6的质数,然后暴力枚举一下就好了。
#include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #include <vector> #include <queue> #include <string> #include <stack> #include <map> #include <set> #include <bitset> #define X first #define Y second #define clr(u,v); memset(u,v,sizeof(u)); #define in() freopen("data","r",stdin); #define out() freopen("ans","w",stdout); #define Clear(Q); while (!Q.empty()) Q.pop(); #define pb push_back using namespace std; typedef long long ll; typedef pair<int, int> pii; const int maxn = 1e6 + 10; const int INF = 0x3f3f3f3f; bool prim[maxn]; int main() { int n; int m = sqrt(maxn + 0.5); for (int i = 2; i <= m; i++) if (!prim[i]) for (int j = i * i; j < maxn; j += i) prim[j] = 1; prim[0] = prim[1] = 1; scanf("%d", &n); for (int i = 1; i <= 1000; i++) if (prim[i*n+1]) { printf("%d ", i); return 0; } return 0; }
B题题意是A和B玩游戏,A有n个单词,B有m个单词,每个人轮流说一句单词,但是不能说重复的单词,说到最后没得说的人输,A先说,问最后A是否能赢。比较简单的贪心,找出两个人单词中的相同数量,这一部分是必须先讲的,可以处理出AB可以讲的单词数,比较一下大小就可以了。
#include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #include <vector> #include <queue> #include <string> #include <stack> #include <map> #include <set> #include <bitset> #define X first #define Y second #define clr(u,v); memset(u,v,sizeof(u)); #define in() freopen("data","r",stdin); #define out() freopen("ans","w",stdout); #define Clear(Q); while (!Q.empty()) Q.pop(); #define pb push_back using namespace std; typedef long long ll; typedef pair<int, int> pii; const int maxn = 1e5 + 10; const int INF = 0x3f3f3f3f; set <string> s; int main() { int n, m; scanf("%d%d", &n, &m); string str; int same = 0; for (int i = 0; i < n; i++) { cin >> str; s.insert(str); } for (int i = 0; i < m; i++) { cin >> str; if (s.count(str)) same++; } int num1 = n - same + (same - same / 2); int num2 = m - same + same / 2; if (num1 > num2) puts("YES"); else puts("NO"); return 0; }
C题题意没看懂。。直接看提示大概是给你n个节点,第i个节点和第a[i]个节点在同一棵树上,问有多少棵树。直接并查集或dfs处理出联通块的数量就行了。
#include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #include <vector> #include <queue> #include <string> #include <stack> #include <map> #include <set> #include <bitset> #define X first #define Y second #define clr(u,v); memset(u,v,sizeof(u)); #define in() freopen("data","r",stdin); #define out() freopen("ans","w",stdout); #define Clear(Q); while (!Q.empty()) Q.pop(); #define pb push_back using namespace std; typedef long long ll; typedef pair<int, int> pii; const int maxn = 1e5 + 10; const int INF = 0x3f3f3f3f; int f[maxn]; int find(int x) { return f[x] == x ? x : f[x] = find(f[x]); } int mix(int x, int y) { int fx = find(x), fy = find(y); if (fx == fy) return 0; f[fx] = fy; return 1; } int main() { int n, x; scanf("%d", &n); int sum = n; for (int i = 1; i <= n; i++) f[i] = i; for (int i = 1; i <= n; i++) { scanf("%d", &x); if(mix(i, x)) sum--; } printf("%d ", sum); return 0; }
D题是给你n边形,然后每次相隔k个点连上一条边,问每次连边后该n边形一共有多少个面。可以考虑,每连一条边,多出的面数是两点直接线段的数量,所以直接树状数组/线段树统计下走过的点,每次增加的时候直接查询他们之间有多少个点就行了。注意要long long,还有要k=min(k,n-k);不然会多算。
#include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #include <vector> #include <queue> #include <string> #include <stack> #include <map> #include <set> #include <bitset> #define X first #define Y second #define clr(u,v); memset(u,v,sizeof(u)); #define in() freopen("data","r",stdin); #define out() freopen("ans","w",stdout); #define Clear(Q); while (!Q.empty()) Q.pop(); #define pb push_back using namespace std; typedef long long ll; typedef pair<int, int> pii; const int maxn = 1e6 + 10; const int INF = 0x3f3f3f3f; ll c[maxn]; int n; int lowbit(int x) { return x & (-x); } ll getsum(int x) { ll ans = 0; while (x > 0) { ans += c[x]; x -= lowbit(x); } return ans; } void updata(int x) { while (x <= n) { c[x]++; x += lowbit(x); } } int main() { int k; scanf("%d%d", &n, &k); k = min(n - k, k); ll add = 1, ans = 1, cur = 1; for (int i = 0; i < n; i++) { updata(cur); if (cur + k <= n) add = getsum(cur + k) - getsum(cur) + 1; else add = getsum(n) - getsum(cur) + getsum((cur + k - 1) % n + 1) + 1; ans += add; if (i == n - 1) cout << ans - 1; else cout << ans << " "; cur = (cur + k - 1) % n + 1; updata(cur); // for (int i=1;i<=n;i++) // cout<<getsum(i)-getsum(i-1)<<" "; // cout<<endl; } return 0; }
这题也可以找规律做。。
#include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #include <vector> #include <queue> #include <string> #include <stack> #include <map> #include <set> #include <bitset> #define X first #define Y second #define clr(u,v); memset(u,v,sizeof(u)); #define in() freopen("data","r",stdin); #define out() freopen("ans","w",stdout); #define Clear(Q); while (!Q.empty()) Q.pop(); #define pb push_back using namespace std; typedef long long ll; typedef pair<int, int> pii; const int maxn = 1e6 + 10; const int INF = 0x3f3f3f3f; int main() { ll n, k; cin >> n >> k; k = min(k, n - k); ll c = 1, add = 1, ans = 1; for (ll i = 1; i <= n; i++) { c += k; if (c > n) { add++; ans += add; add++; c %= n; } else ans += add; if (i == n) cout << ans - 1 << " "; else cout << ans << " "; } return 0; }
总结:这次前面的题比较水,虽然是摸黑打的,手速慢了点,好在D没fst掉,升了171分,直接蓝名了,不枉熬夜到4点。可惜没把房间里十几个D题hack掉,终测完发现自己变成房间第一。总之再接再厉。
2017-01-16 15:34:14