1. 程式人生 > >【AtCoder】ARC090

【AtCoder】ARC090

C - Candies

前一列舉一個i,求第一行的前i個和第二行從第n個到第i個

程式碼

#include <bits/stdc++.h>
#define fi first
#define se second
#define pii pair<int,int>
#define pdi pair<db,int>
#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 ivorysi
using namespace std;
typedef long long int64;
typedef double db;
template<class T>
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<class T>
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 <bits/stdc++.h>
#define fi first
#define se second
#define pii pair<int,int>
#define pdi pair<db,int>
#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 ivorysi
using namespace std;
typedef long long int64;
typedef double db;
template<class T>
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<class T>
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 <bits/stdc++.h>
#define fi first
#define se second
#define pii pair<int,int>
#define pdi pair<db,int>
#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 ivorysi
using namespace std;
typedef long long int64;
typedef double db;
template<class T>
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<class T>
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<pair<int64,int> > 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<int64,int> 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 <bits/stdc++.h>
#define fi first
#define se second
#define pii pair<int,int>
#define pdi pair<db,int>
#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 ivorysi
using namespace std;
typedef long long int64;
typedef double db;
template<class T>
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<class T>
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;
}