Codeforces Round #597 (Div. 2)

mac2026-04-17  0

洛谷博客传送门

A - Good ol’ Numbers Coloring

猜了个 G C D = 1 GCD=1 GCD=1 过了

#include <bits/stdc++.h> using namespace std; typedef long long LL; typedef unsigned long long ULL; int Gcd(int a,int b){if (b == 0) return a; return Gcd(b , a%b);} int Lcm(int a, int b){ return a/Gcd(a,b)*b;} template <class T> void read(T &x) { static char ch; static bool neg; for(ch = neg = 0; ch < '0' || '9' < ch; neg |= ch == '-', ch = getchar()); for(x = 0; '0' <= ch && ch <= '9'; (x *= 10) += ch - '0', ch = getchar()); x = neg ? -x : x; } const int maxn = 1e6 + 10; int main(){ int T; read(T); while(T--){ int a,b; read(a); read(b); if (Gcd(a,b) != 1) cout << "Infinite" << endl; else cout << "Finite" << endl; } return 0; }

B - Restricted RPS

暴力模拟就好,被清空搞了一发

#include <bits/stdc++.h> using namespace std; typedef long long LL; typedef unsigned long long ULL; int Gcd(int a,int b){if (b == 0) return a; return Gcd(b , a%b);} int Lcm(int a, int b){ return a/Gcd(a,b)*b;} template <class T> void read(T &x) { static char ch; static bool neg; for(ch = neg = 0; ch < '0' || '9' < ch; neg |= ch == '-', ch = getchar()); for(x = 0; '0' <= ch && ch <= '9'; (x *= 10) += ch - '0', ch = getchar()); x = neg ? -x : x; } const int maxn = 1e4 + 10; char s[maxn],ans[maxn]; int vis[maxn]; int main(){ int T; read(T); while(T--){ memset(ans,0,sizeof(ans)); memset(vis,0,sizeof(vis)); int n,a,b,c; read(n); read(a); read(b); read(c); scanf("%s",s); int len = n; int res = 0; for(int i=0; i<len; i++){ if (s[i] == 'S' && a > 0){ a--; ans[i] = 'R'; vis[i] = 1; res++; } if (s[i] == 'R' && b > 0){ b--; ans[i] = 'P'; vis[i] = 1; res++; } if (s[i] == 'P' && c > 0){ c--; ans[i] = 'S'; vis[i] = 1; res++; } } for(int i=0; i<len; i++){ if (vis[i] == 0){ if (a > 0){ a--; ans[i] = 'R'; }else if (b > 0){ b--; ans[i] = 'P'; }else if (c > 0){ c--; ans[i] = 'S'; } } vis[i] = 0; } if (res >= (n+1)/2) printf("YES\n%s\n",ans); else printf("NO\n"); } return 0; }

C - Constanze’s Machine

答案就是 u 和 n 连续段的答案的乘,一个连续段的答案可以dp预处理出来

#include <bits/stdc++.h> using namespace std; typedef long long LL; typedef unsigned long long ULL; int Gcd(int a,int b){if (b == 0) return a; return Gcd(b , a%b);} int Lcm(int a, int b){ return a/Gcd(a,b)*b;} template <class T> void read(T &x) { static char ch; static bool neg; for(ch = neg = 0; ch < '0' || '9' < ch; neg |= ch == '-', ch = getchar()); for(x = 0; '0' <= ch && ch <= '9'; (x *= 10) += ch - '0', ch = getchar()); x = neg ? -x : x; } const int maxn = 1e6 + 10; const LL mod = 1e9 + 7; LL dp[maxn][2],len[maxn]; int main(){ dp[2][1] = dp[2][0] = 1; len[2] = 2; len[1] = 1; for(int i=3; i<=1E5; i++){ dp[i][1] = dp[i-1][0]; dp[i][0] = (dp[i-1][1] + dp[i-1][0]) % mod; len[i] = (dp[i][1] + dp[i][0]) % mod; } string s; cin >> s; LL ans = 1,tot = 1,tag = 1; for(int i=0; i < (int)s.length()-1; i++){ if (s[i] == 'm' || s[i] == 'w'){ tag = 0; break; } if (s[i] == s[i+1]){ tot++; }else{ if (s[i] == 'u' || s[i] == 'n'){ ans = ans * len[tot] % mod; } tot = 1; } } char ch = s[s.length()-1]; if (tot > 1 && (ch == 'u'||ch == 'n')){ ans = ans * len[tot] % mod; } if (tag) cout << ans << endl; else cout << 0 << endl; return 0; }

D - Shichikuji and Power Grid

贪心,每次在花费最小的地方建立一个基站,每建完了一个基站,去更新其他基站的最小花费即可。

#include <bits/stdc++.h> using namespace std; typedef long long LL; typedef unsigned long long ULL; int Gcd(int a,int b){if (b == 0) return a; return Gcd(b , a%b);} int Lcm(int a, int b){ return a/Gcd(a,b)*b;} template <class T> void read(T &x) { static char ch; static bool neg; for(ch = neg = 0; ch < '0' || '9' < ch; neg |= ch == '-', ch = getchar()); for(x = 0; '0' <= ch && ch <= '9'; (x *= 10) += ch - '0', ch = getchar()); x = neg ? -x : x; } const int maxn = 1e6 + 10; struct node{ int x,y,id; }p[maxn]; LL c[maxn],k[maxn]; int ok[maxn],pre[maxn]; vector<int> Node; vector<pair<int,int> > Edge; LL getdis(node a,node b){ LL dis = abs(a.x-b.x) + abs(a.y-b.y); return dis * (k[a.id] + k[b.id]); } int main(){ int n; read(n); for(int i=1; i<=n; i++) { read(p[i].x); read(p[i].y); p[i].id = i; } for(int i=1; i<=n; i++){ read(c[i]); } for(int j=1; j<=n; j++){ read(k[j]); } LL ans = 0; for(int i=1; i<=n; i++){ int mn = INT_MAX,u = 0; for(int j=1; j<=n; j++){ if (!ok[j] && c[j] < mn){ mn = c[j]; u = j; } } ans += mn; if (pre[u] == 0) Node.push_back(u); else Edge.push_back(make_pair(pre[u],u)); ok[u] = 1; for(int j=1; j<=n; j++){ if (!ok[j]){ LL dis = getdis(p[u],p[j]); if (dis < c[j]){ c[j] = dis; pre[j] = u; } } } } cout << ans << endl; cout << Node.size() << endl; for(auto u : Node){ cout << u << ' '; } cout << endl; cout << Edge.size() << endl; for(auto now : Edge){ cout << now.first << ' ' << now.second << endl; } return 0; }

F - Daniel and Spring Cleaning

推公式的题目,看了题解才会,定义 f ( l , r ) f(l,r) f(l,r) [ l , r ) [l,r) [l,r) 区间内满足条件的 ( x , y ) (x,y) (x,y) 的个数。

首先是一个很重要的结论,直接可以降低复杂度

f ( 2 l , 2 r ) = 3 ∗ f ( l , r ) f(2l,2r)=3*f(l,r) f(2l,2r)=3f(l,r)

证明也很好懂,乘2相当于左移一位,因此在 l , r l,r l,r 最后都多了一位,对于这一位来说,必须是 ( 0 , 1 ) , ( 1 , 0 ) , ( 0 , 1 ) (0,1),(1,0),(0,1) (0,1),(1,0),(0,1) 中的一种,才能满足 x + y = x x o r y x + y = x \quad xor \quad y x+y=xxory,原来本身满足条件的数量是 f ( l , r ) f(l,r) f(l,r) 因此 f ( 2 l , 2 r ) = 3 ∗ f ( l , r ) f(2l,2r)=3*f(l,r) f(2l,2r)=3f(l,r)

l , r l,r l,r 都是偶数的时候,我们可以直接除2计算,复杂度可以向 O ( l o g ) O(log) O(log) 靠拢。

不过当其中一个是奇数的时候,我们就可以通过+1,或者-1把它变成偶数。

首先定义 g ( x , n ) g(x,n) g(x,n) 1 ≤ y < n 1 \leq y < n 1y<n,中满足 x + y = x x o r y x + y = x \quad xor \quad y x+y=xxory 的个数,

l l l 是偶数的时候, f ( l , r ) = f ( l + 1 , r ) + 2 ∗ ( g ( l , r ) − g ( l , l ) ) f(l,r)=f(l+1,r)+2*(g(l,r)-g(l,l)) f(l,r)=f(l+1,r)+2(g(l,r)g(l,l))

r r r 是偶数的时候, f ( l , r ) = f ( l , r − 1 ) + 2 ∗ ( g ( r − 1 , r ) − g ( r − 1 , l ) ) f(l,r) = f(l,r-1)+2*(g(r-1,r)-g(r-1,l)) f(l,r)=f(l,r1)+2(g(r1,r)g(r1,l))

现在只需要快速计算 g ( x , y ) g(x,y) g(x,y) 即可

g ( x , n ) g(x,n) g(x,n) 分段计算,每一段就是

g ( x , n ) = 2 z e r o s + g ( x , n − l o w b i t ( n ) ) g(x,n)=2^{zeros} + g(x,n-lowbit(n)) g(x,n)=2zeros+g(x,nlowbit(n))

每lowbit是一段,相当从b的二进制最后一位往前数,数到一个1就分一段,这样分段保证了当前的二进制位前面的位,在这个段内,是完全相同的。

那么这个段内的答案,和a的二进制串在段之内的0的个数有关,只要a的那一位是0,b的对应位是0或者1都可以,而a那一位是1,b必须是0,对答案没有贡献。a二进制串后缀的0的个数记为 zeros ,那么段内的答案就是 2 z e r o s 2^{zeros} 2zeros

统计答案即可,复杂度 O ( l o g 2 ( n ) ) O(log^2(n)) O(log2(n))

代码

#include <bits/stdc++.h> using namespace std; typedef long long LL; typedef unsigned long long ULL; int Gcd(int a,int b){if (b == 0) return a; return Gcd(b , a%b);} int Lcm(int a, int b){ return a/Gcd(a,b)*b;} template <class T> void read(T &x) { static char ch; static bool neg; for(ch = neg = 0; ch < '0' || '9' < ch; neg |= ch == '-', ch = getchar()); for(x = 0; '0' <= ch && ch <= '9'; (x *= 10) += ch - '0', ch = getchar()); x = neg ? -x : x; } const int maxn = 1e6 + 10; LL g(LL a,LL b){ LL ans = 0,cnt = 0; for(LL i=1; i<=b; i<<=1){ if (b & i){ b ^= i; // b -= lowbit(b); if (!(a & b)) ans += (1 << cnt); // 后面的位也满足 a + b = a ^ b 这个区间段上就有答案 // a的某bit是0,那b的那个bit随便是0还是1,如果a是1,b必须是0,相当于 ans *= 1 没有贡献 } if (! (a & i)) cnt++; } return ans; } int tot = 0; LL f(LL l,LL r){ if (l == r) return 0; if (l == 0) return 2*r - 1 + f(1,r); LL ans = 0; if (l & 1){ ans += 2 * (g(l,r) - g(l,l)); l++; } if (r & 1){ ans += 2 * (g(r-1,r) - g(r-1,l)); r--; } return ans + 3 * f(l/2,r/2); } int main(){ int T; read(T); while(T--){ int l,r; read(l); read(r); cout << f(l,r+1) << endl; } return 0; }
最新回复(0)