Codeforces Round #428 (Div. 2)
A 看懂题目意思就知道做了
#include<bits/stdc++.h> using namespace std; #pragma comment(linker, "/STACK:102400000,102400000") #define rep(i,a,b) for (int i=a; i<=b; ++i) #define per(i,b,a) for (int i=b; i>=a; --i) #define mes(a,b) memset(a,b,sizeof(a)) #define INF 0x3f3f3f3f #define MP make_pair #define PB push_back #define fi first #define se second typedef long long ll; const int N = 200005; int n, k, a[110]; int main() { scanf("%d%d", &n, &k); int cnt=0, sum=0, ans=0; rep(i,1,n) { scanf("%d", &a[i]); cnt += a[i]; sum += min(cnt, 8); cnt -= min(cnt, 8); if(sum >= k) { ans = i; break; } } if(ans) printf("%d ", ans); else puts("-1"); return 0; }
B 模拟,有点坑
tags:统计出 4人座、2人座、1人座 的数量,然后变化即可
#include<bits/stdc++.h> using namespace std; #pragma comment(linker, "/STACK:102400000,102400000") #define rep(i,a,b) for (int i=a; i<=b; ++i) #define per(i,b,a) for (int i=b; i>=a; --i) #define mes(a,b) memset(a,b,sizeof(a)) #define INF 0x3f3f3f3f #define MP make_pair #define PB push_back #define fi first #define se second typedef long long ll; const int N = 10005; int n, k, a[N], b1, b2, b3; int main() { scanf("%d%d", &n, &k); rep(i,1,k) scanf("%d", &a[i]); b1=n*2, b2=n, b3=0; rep(i,1,k) if(a[i]>=4) { int x=min(b2, a[i]/4); b2 -= x, a[i] -= x*4; } if(b2) b1+=b2, b3+=b2; rep(i,1,k) if(a[i]) { int x=min(b1, a[i]/2); b1 -= x, a[i] -= x*2; x=min(b3, a[i]); b3 -= x, a[i] -= x; if(a[i] && b1) --b1, --a[i]; if(a[i]) { return 0*printf("NO "); } } puts("YES"); return 0; }
C 水 dfs
#include<bits/stdc++.h> using namespace std; #pragma comment(linker, "/STACK:102400000,102400000") #define rep(i,a,b) for (int i=a; i<=b; ++i) #define per(i,b,a) for (int i=b; i>=a; --i) #define mes(a,b) memset(a,b,sizeof(a)) #define INF 0x3f3f3f3f #define MP make_pair #define PB push_back #define fi first #define se second typedef long long ll; const int N = 200005; int n; double ans; vector<int > G[N]; void dfs(int u, int fa, double p, int len) { if(G[u].size()==1 && u!=1) ans += p*len; double p2 = p*1/(G[u].size()-1+(u==1)); for(auto v : G[u]) if(v!=fa) { dfs(v, u, p2, len+1); } } int main() { scanf("%d", &n); int u, v; rep(i,1,n-1) { scanf("%d%d", &u, &v); G[u].PB(v); G[v].PB(u); } dfs(1, 0, 1, 0); printf("%.6f ", ans); return 0; }
D 容斥、莫比乌斯反演
tags:
考虑枚举 gcd, f(d)=∑k 表示gcd为d的所有子集的长度和, 设 F(d)=∑f(n) 要求 d|n 。
如有cnt个数是d的倍数,易知 F(d)=1*C(cnt,1)+2*(cnt,2)+.....+cnt*C(cnt,cnt) = cnt* ( C(cnt-1,0)+C(cnt-1,1)+.....+C(cnt-1,cnt-1) ) = cnt*2^(cnt-1) 。 所以我们可以轻松地求出F(d) 。
下面考虑去重的问题:
方法1:
根据莫比乌斯反演, f(d) = ∑ u(n/d) F(n) 要求 d|n 。 答案就是 ans += d*f(d) 要求 2<=d<=max 。
#include<bits/stdc++.h> using namespace std; #pragma comment(linker, "/STACK:102400000,102400000") #define rep(i,a,b) for (int i=a; i<=b; ++i) #define per(i,b,a) for (int i=b; i>=a; --i) #define mes(a,b) memset(a,b,sizeof(a)) #define INF 0x3f3f3f3f #define MP make_pair #define PB push_back #define fi first #define se second typedef long long ll; const int N = 1000005, mod = 1e9+7; int n, a[N], cnt[N], vis[N]; ll fpow(ll a,int b) { ll ans=1; for(; b; a=a*a%mod, b>>=1) if(b&1) ans=ans*a%mod; return ans; } int mu[N]; void mobius(int mn) { mu[1] = 1; for(int i=1; i<=mn; ++i) for(int j=i+i; j<=mn; j+=i) mu[j] -= mu[i]; } int main() { scanf("%d", &n); int mx = 0; rep(i,1,n) { scanf("%d", &a[i]); ++vis[a[i]], mx = max(mx, a[i]); } rep(i,1,mx) for(int j=i; j<=mx; j+=i) cnt[i] += vis[j]; mobius(mx); ll ans = 0; rep(i,2,mx) if(cnt[i]) { ll tmp = 0; for(int j=i; j<=mx; j+=i) if(mu[j/i] && cnt[j]) { ( tmp += (1LL*mu[j/i]*cnt[j]%mod)*fpow(2, cnt[j]-1)%mod ) %= mod; } ( ans += 1LL*i*tmp%mod ) %= mod; } printf("%lld ", (ans+mod)%mod ); return 0; }
方法2:
先假定 F(d) 就是所有gcd为d的所有子集的长度和,但这里其实多算了gcd为d 的倍数的集合,所以要减去gcd为d的倍数的集合的贡献。
所以只要反着来枚举即可。
#include<bits/stdc++.h> using namespace std; #pragma comment(linker, "/STACK:102400000,102400000") #define rep(i,a,b) for (int i=a; i<=b; ++i) #define per(i,b,a) for (int i=b; i>=a; --i) #define mes(a,b) memset(a,b,sizeof(a)) #define INF 0x3f3f3f3f #define MP make_pair #define PB push_back #define fi first #define se second typedef long long ll; const int N = 1000005, mod = 1e9+7; int n, a[N], cnt[N], vis[N]; ll sum[N]; ll fpow(ll a,int b) { ll ans=1; for(; b; a=a*a%mod, b>>=1) if(b&1) ans=ans*a%mod; return ans; } int main() { scanf("%d", &n); int mx = 0; rep(i,1,n) { scanf("%d", &a[i]); ++vis[a[i]], mx = max(mx, a[i]); } rep(i,1,mx) for(int j=i; j<=mx; j+=i) cnt[i] += vis[j]; ll ans = 0; per(i,mx,2) if(cnt[i]) { ( sum[i] = 1LL*cnt[i]*fpow(2LL, cnt[i]-1)%mod ) %= mod; for(int j=2*i; j<=mx; j+=i) sum[i] -= sum[j], ( sum[i] += mod ) %= mod; ( ans += sum[i]*i%mod ) %= mod; } printf("%lld ", (ans+mod)%mod ); return 0; }