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;}