Codeforces Round #548 (Div. 2)
Posted hjmmm
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Codeforces Round #548 (Div. 2)相关的知识,希望对你有一定的参考价值。
比赛链接
cf
A
最后一位判定
#include <cstdlib>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <queue>
#include <vector>
#include <map>
#define P(x, y) 1ll * (x) * inv(y) % P
using namespace std;
typedef long long ll;
const int N = 65005;
const ll P = 1e9 + 7;
int n;
ll ans;
char str[N];
int main(){
scanf("%d%s", &n, str + 1);
for(int i = 1; i <= n; ++i){
if(!((str[i] - '0') & 1)) ans += i;
}
printf("%lld", ans);
return 0;
}
B
倒叙维护最大值
#include <cstdlib>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <queue>
#include <vector>
#include <map>
#define P(x, y) 1ll * (x) * inv(y) % P
using namespace std;
typedef long long ll;
const int N = 2e5 + 5;
const ll P = 1e9 + 7;
int n, a[N], lim;
ll ans;
int main(){
scanf("%d", &n);
for(int i = 1, x; i <= n; ++i){
scanf("%d", &a[i]);
}
lim = a[n]; ans += a[n];
for(int i = n - 1; i >= 1; --i){
lim = max(0, min(lim - 1, a[i]));
ans += lim;
}
printf("%lld\n", ans);
return 0;
}
C
所有方案 - 全是红边的方案
并查集维护
#include <cstdlib>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <queue>
#include <vector>
#include <map>
#include <set>
using namespace std;
typedef long long ll;
typedef pair<int, int> PII;
const int N = 1e5 + 5;
const ll P = 1e9 + 7;
int n, m; ll ans;
int size[N], fa[N];
inline ll qpow(ll x, ll y){
ll res = 1;
while(y){
if(y & 1) res = res * x % P;
x = x * x % P; y >>= 1;
}
return res;
}
int find(int x){return x == fa[x] ? x : fa[x] = find(fa[x]);}
inline void merge(int x, int y){x = find(x), y = find(y), fa[x] = y, size[y] += size[x];}
int main(){
scanf("%d%d", &n, &m);
ans = qpow(n, m);
for(int i = 1; i <= n; ++i) fa[i] = i, size[i] = 1;
for(int i = 1, x, y, z; i < n; ++i){
scanf("%d%d%d", &x, &y, &z);
if(!z) merge(x, y);
}
for(int i = 1; i <= n; ++i){
if(fa[i] == i){
ans = (ans + P - qpow(size[i], m)) % P;
}
}
printf("%lld\n", ans);
return 0;
}
然后我就自闭了?
D
给定数m \(m \leq 1e5\)
进行如下流程:
1.rand一个[1, m]的数
2.把它接在序列a后面
3.如果a的gcd等于1 退出 否则进行第一步
求进行流程次数的期望
前面那个\(\frac{(m-m/x)}{m}\)是抽到的数不是自己的倍数的概率
\(\frac{(m-m/x)}{m}*dp[x] = 1 + \sum_{d|x}^{m} \frac{dp[d]*c[d]}{m}\)
当然容斥那里用莫比乌斯函数也ok啦【因为懒所以这么写了
#include <cstdlib>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <queue>
#include <vector>
#include <map>
#include <set>
using namespace std;
typedef long long ll;
typedef pair<int, int> PII;
const int N = 1e5 + 5;
const ll P = 1e9 + 7;
inline ll qpow(ll x, ll y){
ll res = 1;
while(y){
if(y & 1) res = res * x % P;
x = x * x % P; y >>= 1;
}
return res;
}
int cnt[N], m, invm;
vector<int> d[N];
ll f[N];
inline void init(){
for(int i = (m >> 1); i > 1; --i)
for(int j = (i << 1); j <= m; j += i)
d[j].push_back(i);
invm = qpow(m, P - 2);
}
inline void cut(int x){
for(int i : d[x]) cnt[i] -= cnt[x];
}
int main(){
scanf("%d", &m), init();
for(int i = 2; i <= m; ++i){
for(int j : d[i]) cnt[j] = m / j;
cnt[i] = m / i, cut(i);
for(int j : d[i]){
f[i] = (f[i] + f[j] * cnt[j] % P) % P;
cut(j);
}
f[i] = ((f[i] + 1ll * m) % P * qpow(m - m / i, P - 2) % P) % P;
}
ll ans = 0;
for(int i = 2; i <= m; ++i) ans = (ans + f[i]) % P;
ans = (ans * invm % P + 1) % P;
printf("%lld", ans);
return 0;
}
E
有n个点 m个集合
每个点有一个权值pi 有一个集合编号ci
每次删掉一个点之后查询每个集合选一个权值的最大mex
所有数据小于等于5000
倒着加边 边加边匹配
#include <cstdlib>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <queue>
#include <vector>
#include <map>
#include <set>
#define mp(x, y) make_pair(x, y)
using namespace std;
typedef long long ll;
typedef pair<int, int> PII;
const int N = 5005;
int n, m;
struct Edge{int v, next;}edge[N];
int head[N], esize;
inline void addedge(int x, int y){
edge[++esize] = (Edge){y, head[x]}, head[x] = esize;
}
int p[N], c[N], day[N], ans;
int d, bk[N], match[N];
bool vis[N], del[N];
bool dfs(int x){
for(int i = head[x], vv; ~i; i = edge[i].next){
vv = edge[i].v;
if(!vis[vv]){
vis[vv] = 1;
if(!match[vv] || dfs(match[vv])){
match[vv] = x; return 1;
}
}
}
return 0;
}
int main(){
memset(head, -1, sizeof(head));
scanf("%d%d", &n, &m);
for(int i = 1; i <= n; ++i) scanf("%d", &p[i]), ++p[i];
for(int i = 1; i <= n; ++i) scanf("%d", &c[i]);
scanf("%d", &d);
for(int i = 1; i <= d; ++i) scanf("%d", &bk[i]), del[bk[i]] = 1;
ans = 1;
for(int i = 1; i <= n; ++i) if(!del[i]) addedge(p[i], c[i]);
for(int i = d; i >= 1; --i){
memset(vis, 0, sizeof(vis));
while(dfs(ans)){++ans; memset(vis, 0, sizeof(vis));}
day[i] = ans - 1;
addedge(p[bk[i]], c[bk[i]]);
}
for(int i = 1; i <= d; ++i) printf("%d\n", day[i]);
return 0;
}
F
太神仙了慢慢搞
一眼扫描线?
以上是关于Codeforces Round #548 (Div. 2)的主要内容,如果未能解决你的问题,请参考以下文章
C. Edgy Trees Codeforces Round #548 (Div. 2) 并查集求连通块
Codeforces Round #548 (Div. 2) C dp or 排列组合
Codeforces Round #436 E. Fire(背包dp+输出路径)