博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【AtCoder】ARC090
阅读量:5136 次
发布时间:2019-06-13

本文共 8304 字,大约阅读时间需要 27 分钟。

C - Candies

前一枚举一个i,求第一行的前i个和第二行从第n个到第i个

代码

#include 
#define fi first#define se second#define pii pair
#define pdi pair
#define mp make_pair#define pb push_back#define enter putchar('\n')#define space putchar(' ')#define eps 1e-8#define mo 974711#define MAXN 1000005//#define ivorysiusing namespace std;typedef long long int64;typedef double db;template
void read(T &res) { res = 0;char c = getchar();T f = 1; while(c < '0' || c > '9') { if(c == '-') f = -1; c = getchar(); } while(c >= '0' && c <= '9') { res = res * 10 + c - '0'; c = getchar(); } res *= f;}template
void out(T x) { if(x < 0) {x = -x;putchar('-');} if(x >= 10) { out(x / 10); } putchar('0' + x % 10);}int N,sum[2][105];void Solve() { read(N); for(int i = 0 ; i <= 1 ; ++i) { for(int j = 1 ; j <= N ; ++j) { read(sum[i][j]); } } for(int i = 1 ; i <= N ; ++i) { sum[0][i] += sum[0][i - 1]; } for(int i = N ; i >= 1 ; --i) { sum[1][i] += sum[1][i + 1]; } int ans = 0; for(int i = 1 ; i <= N ; ++i) { ans = max(ans,sum[0][i] + sum[1][i]); } out(ans);enter;}int main() {#ifdef ivorysi freopen("f1.in","r",stdin);#endif Solve(); return 0;}

D - People on a Line

带权并查集,维护每个点到父亲节点的距离即可

代码

#include 
#define fi first#define se second#define pii pair
#define pdi pair
#define mp make_pair#define pb push_back#define enter putchar('\n')#define space putchar(' ')#define eps 1e-8#define mo 974711#define MAXN 100005//#define ivorysiusing namespace std;typedef long long int64;typedef double db;template
void read(T &res) { res = 0;char c = getchar();T f = 1; while(c < '0' || c > '9') { if(c == '-') f = -1; c = getchar(); } while(c >= '0' && c <= '9') { res = res * 10 + c - '0'; c = getchar(); } res *= f;}template
void out(T x) { if(x < 0) {x = -x;putchar('-');} if(x >= 10) { out(x / 10); } putchar('0' + x % 10);}int N,M;int fa[MAXN],dis[MAXN];int getfa(int u) { if(u == fa[u]) return u; else { int t = getfa(fa[u]); dis[u] += dis[fa[u]]; return fa[u] = t; }}void Solve() { read(N);read(M); for(int i = 1 ; i <= N ; ++i) { fa[i] = i;dis[i] = 0; } int l,r,d; for(int i = 1 ; i <= M ; ++i) { read(l);read(r);read(d); if(getfa(l) == getfa(r)) { if(dis[r] - dis[l] != d) { puts("No"); return; } } else { int p = getfa(r),q = getfa(l); fa[p] = q; dis[p] = dis[l] - dis[r] + d; } } puts("Yes");}int main() {#ifdef ivorysi freopen("f1.in","r",stdin);#endif Solve(); return 0;}

E - Avoiding Collision

先计算所有的情况,再计算不合法的情况

枚举在边上撞上的情况,很容易发现两个人撞上只会在一条边上撞上,且如果在这条边撞上在包括这条边的所有路径里其他边都不会再撞上,然后计算穿过这条边\(u,v\)的方案数,是从\(S\)\(u\)和从\(v\)\(T\)的方案数相乘

然后枚举在点撞上的情况,是到\(S\)和到\(T\)最短路距离相同的点

代码

#include 
#define fi first#define se second#define pii pair
#define pdi pair
#define mp make_pair#define pb push_back#define enter putchar('\n')#define space putchar(' ')#define eps 1e-8#define mo 974711#define MAXN 200005//#define ivorysiusing namespace std;typedef long long int64;typedef double db;template
void read(T &res) { res = 0;char c = getchar();T f = 1; while(c < '0' || c > '9') { if(c == '-') f = -1; c = getchar(); } while(c >= '0' && c <= '9') { res = res * 10 + c - '0'; c = getchar(); } res *= f;}template
void out(T x) { if(x < 0) {x = -x;putchar('-');} if(x >= 10) { out(x / 10); } putchar('0' + x % 10);}const int MOD = 1000000007;int N,M,S,T;struct node { int to,next; int64 val;}E[MAXN * 2];int head[MAXN],sumE,id[MAXN],on,dp[2][MAXN],ans;int64 dis[2][MAXN];bool vis[MAXN];int inc(int a,int b) { return a + b >= MOD ? a + b - MOD : a + b;}int mul(int a,int b) { return 1LL * a * b % MOD;}void add(int u,int v,int64 c) { E[++sumE].to = v; E[sumE].next = head[u]; E[sumE].val = c; head[u] = sumE;}priority_queue
> Q;void dijkstra(int u,int64 *d) { for(int i = 1 ; i <= N ; ++i) d[i] = 1e18; memset(vis,0,sizeof(vis)); d[u] = 0; Q.push(mp(-d[u],u)); while(!Q.empty()) { pair
now = Q.top();Q.pop(); if(vis[now.se]) continue; int u = now.se; vis[u] = 1; for(int i = head[u] ; i ; i = E[i].next) { int v = E[i].to; if(!vis[v] && d[v] > d[u] + E[i].val) { d[v] = d[u] + E[i].val; Q.push(mp(-d[v],v)); } } }}bool cmp(int a,int b) { return dis[on][a] < dis[on][b];}void Process() { for(int i = 1 ; i <= N ; ++i) id[i] = i; sort(id + 1,id + N + 1,cmp); dp[on][id[1]] = 1; for(int i = 1 ; i <= N ; ++i) { int u = id[i]; for(int j = head[u] ; j ; j = E[j].next) { int v = E[j].to; if(dis[on][v] - dis[on][u] == E[j].val) { dp[on][v] = inc(dp[on][v],dp[on][u]); } } }}void Solve() { read(N);read(M); read(S);read(T); int u,v;int64 d; for(int i = 1 ; i <= M ; ++i) { read(u);read(v);read(d); add(u,v,d);add(v,u,d); } dijkstra(S,dis[0]); dijkstra(T,dis[1]); on = 0;Process(); on = 1;Process(); ans = mul(dp[0][T],dp[0][T]); for(int u = 1 ; u <= N ; ++u) { for(int i = head[u] ; i ; i = E[i].next) { int v = E[i].to; if(dis[0][u] + dis[1][v] + E[i].val == dis[0][T]) { if(dis[1][v] + E[i].val - dis[0][u] > 0 && dis[1][v] + E[i].val - dis[0][u] < 2 * E[i].val) { ans = inc(ans,MOD - mul(mul(dp[0][u],dp[1][v]),mul(dp[1][v],dp[0][u]))); } } } if(dis[0][u] == dis[1][u]) { ans = inc(ans,MOD - mul(mul(dp[0][u],dp[1][u]),mul(dp[0][u],dp[1][u]))); } } out(ans);enter;}int main() {#ifdef ivorysi freopen("f1.in","r",stdin);#endif Solve(); return 0;}

F - Number of Digits

考虑一下数的个数最多不超过10^8个

如果开头的数数位是8或以上,最多只进一次位

我们从1到\(\frac{S}{8}\)枚举位数,设开头的数数位为a
如果全为数位长为a的数,如果有i个,就是\(10^{a} - 10^{a - 1} - i + 1\)
否则就是\(1\)

然后我们枚举开头数位是1到7,枚举跨了几个数位,最多是跨到8

然后枚举\(10^a - 10^{a - 1}\)为我开头数位选了几个,计算终点数位能否被整除,选的个数符不符合要求,不断+1即可

代码

#include 
#define fi first#define se second#define pii pair
#define pdi pair
#define mp make_pair#define pb push_back#define enter putchar('\n')#define space putchar(' ')#define eps 1e-8#define mo 974711#define MAXN 200005//#define ivorysiusing namespace std;typedef long long int64;typedef double db;template
void read(T &res) { res = 0;char c = getchar();T f = 1; while(c < '0' || c > '9') { if(c == '-') f = -1; c = getchar(); } while(c >= '0' && c <= '9') { res = res * 10 + c - '0'; c = getchar(); } res *= f;}template
void out(T x) { if(x < 0) {x = -x;putchar('-');} if(x >= 10) { out(x / 10); } putchar('0' + x % 10);}const int MOD = 1000000007;int S;int pw[15],sum[15];int inc(int a,int b) { return a + b >= MOD ? a + b - MOD : a + b;}int mul(int a,int b) { return 1LL * a * b % MOD;}int fpow(int x,int c) { int res = 1,t = x; while(c) { if(c & 1) res = mul(res,t); t = mul(t,t); c >>= 1; } return res;}void update(int &x,int y) { x = inc(x,y);}void Solve() { read(S); pw[0] = 1; for(int i = 1 ; i <= 8 ; ++i) { pw[i] = pw[i - 1] * 10; sum[i] = (pw[i] - pw[i - 1]) * i; sum[i] += sum[i - 1]; } int T = min(S,20000000); int ans = 0; for(int i = 1 ; i <= T ; ++i) { int a = S / i; if(a >= 8) { if(S % i == 0) { update(ans,inc(inc(fpow(10,a),MOD - fpow(10,a - 1)),MOD - i + 1)); } else { update(ans,1); } } else break; } for(int a = 1 ; a <= 7 ; ++a) { if(S < a) break; if(S % a == 0 && S / a <= pw[a] - pw[a - 1]) update(ans,pw[a] - pw[a - 1] - S / a + 1); for(int b = 1 ; b <= 7 ; ++b) { if(a + b >= 9) break; if(sum[a + b] - sum[a - 1] < S) continue; int t = sum[a + b - 1] - sum[a]; if(t > S) break; int rem = S - t; for(int i = 1 ; i <= pw[a] - pw[a - 1] ; ++i) { if(i * a >= rem) break; if((rem - i * a) % (a + b) == 0) { if((rem - (i * a)) / (a + b) <= pw[a + b] - pw[a + b - 1]) update(ans,1); } } } } out(ans);enter;}int main() {#ifdef ivorysi freopen("f1.in","r",stdin);#endif Solve(); return 0;}

转载于:https://www.cnblogs.com/ivorysi/p/10076955.html

你可能感兴趣的文章
你是这样理解shell编程的嘛?
查看>>
Assets和Raw区别
查看>>
【luogu4185】 [USACO18JAN]MooTube [并查集]
查看>>
手机号脱敏处理
查看>>
CI控制器调用内部方法并载入相应模板的做法
查看>>
Hdu - 1002 - A + B Problem II
查看>>
HDU - 2609 - How many
查看>>
每天CookBook之Python-003
查看>>
每天CookBook之Python-004
查看>>
Android设置Gmail邮箱
查看>>
StringBuffer的用法
查看>>
js编写时间选择框
查看>>
PHP压缩文件操作
查看>>
Java数据结构和算法(四)--链表
查看>>
JIRA
查看>>
ssl介绍以及双向认证和单向认证原理
查看>>
【BZOJ2441】【中山市选2011】小W的问题(树状数组+权值线段树)
查看>>
小技巧——直接在目录中输入cmd然后就打开cmd命令窗口
查看>>
深浅拷贝(十四)
查看>>
由级别和性格特征将程序员分类 ---看看你属于哪一种
查看>>