zoukankan      html  css  js  c++  java
  • 【AtCoder】AGC017

    A - Biscuits

    dp[i][0/1]表示当前和是偶数还是奇数,直接转移即可

    #include <bits/stdc++.h>
    #define fi first
    #define se second
    #define pii pair<int,int>
    #define mp make_pair
    #define pb push_back
    #define space putchar(' ')
    #define enter putchar('
    ')
    #define MAXN 1000005
    #define eps 1e-10
    //#define ivorysi
    using namespace std;
    typedef long long int64;
    typedef unsigned int u32;
    typedef double db;
    template<class T>
    void read(T &res) {
        res = 0;T f = 1;char c = getchar();
        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,P;
    int a[55];
    int64 dp[55][2];
    void Solve() {
        read(N);read(P);
        for(int i = 1 ; i <= N ; ++i) read(a[i]);
        dp[0][0] = 1;
        for(int i = 1 ; i <= N ; ++i) {
    	int k = a[i] & 1;
    	dp[i][0] = dp[i - 1][0];dp[i][1] = dp[i - 1][1];
    	dp[i][k ^ 0] += dp[i - 1][0];
    	dp[i][k ^ 1] += dp[i - 1][1];
        }
        out(dp[N][P]);enter;
    }
    int main() {
    #ifdef ivorysi
        freopen("f1.in","r",stdin);
    #endif
        Solve();
    }
    

    B - Moderate Differences

    A和B差值在(N imes C)((N-1) imes D)之间肯定能达到
    因为下降操作和上升操作差不多,那么我们默认所有的下降操作都在前面
    容易发现,当我们进行(i)次至少为(C)的下降后
    (-i imes C + (N - 1 - i) imes C)(-i imes C + (N - 1 - i) imes D)之间的也可以达到
    且这样能构造最多的重合的区间

    #include <bits/stdc++.h>
    #define fi first
    #define se second
    #define pii pair<int,int>
    #define mp make_pair
    #define pb push_back
    #define space putchar(' ')
    #define enter putchar('
    ')
    #define MAXN 1000005
    #define eps 1e-10
    //#define ivorysi
    using namespace std;
    typedef long long int64;
    typedef unsigned int u32;
    typedef double db;
    template<class T>
    void read(T &res) {
        res = 0;T f = 1;char c = getchar();
        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;
    int64 A,B,C,D;
    bool check(int64 a,int64 b) {
        return B - A >= a && B - A <= b;
    }
    void Solve() {
        read(N);read(A);read(B);read(C);read(D);
        for(int i = 0 ; i <= N - 1 ; ++i) {
    	int64 u = (N - 1 - i) * D - C * i,d = (N - 1 - i) * C - C * i;
    	if(check(d,u)) {puts("YES");return;}
    	u = C * i - (N - 1 - i) * C,d = C * i - (N - 1 - i) * D;
    	if(check(d,u)) {puts("YES");return;}
        }
        puts("NO");
    }
    int main() {
    #ifdef ivorysi
        freopen("f1.in","r",stdin);
    #endif
        Solve();
    }
    

    C - Snuke and Spells

    假如(i)出现了(A[i])次,那么覆盖([i - A[i],i])这个区间,然后找([0,L])没有被覆盖的区间长度,就是答案
    可以(O(1))处理修改

    #include <bits/stdc++.h>
    #define fi first
    #define se second
    #define pii pair<int,int>
    #define mp make_pair
    #define pb push_back
    #define space putchar(' ')
    #define enter putchar('
    ')
    #define MAXN 1000005
    #define eps 1e-10
    //#define ivorysi
    using namespace std;
    typedef long long int64;
    typedef unsigned int u32;
    typedef double db;
    template<class T>
    void read(T &res) {
        res = 0;T f = 1;char c = getchar();
        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 A[MAXN];
    int cnt[MAXN],cov[MAXN],ans;
    void Solve() {
        read(N);read(M);
        for(int i = 1 ; i <= N ; ++i) {
    	read(A[i]);
    	cnt[A[i]]++;
    	cov[A[i] - cnt[A[i]] + 1]++;
        }
        for(int i = 1 ; i <= N ; ++i) {
    	if(!cov[i]) ++ans;
        }
        int x,y;
        for(int i = 1 ; i <= M ; ++i) {
    	read(x);read(y);
    	if(A[x] - cnt[A[x]] + 1 >= 1) {
    	    if(!--cov[A[x] - cnt[A[x]] + 1]) ++ans;
    	}
    	--cnt[A[x]];
    	A[x] = y;
    	++cnt[A[x]];
    	if(A[x] - cnt[A[x]] + 1 >= 1) {
    	    if(!cov[A[x] - cnt[A[x]] + 1]++) --ans;
    	}
    	out(ans);enter;
        }
    }
    int main() {
    #ifdef ivorysi
        freopen("f1.in","r",stdin);
    #endif
        Solve();
    }
    

    D - Game on Tree

    一个点的sg函数值显然是0,而一个树加一条边一个点的sg函数值是这棵树的sg函数值+1

    证明,设新加的边为(u,v)(u)(v)的祖先,若断掉新加的边,则sg值是0

    否则断树中的边,sg函数值为([0,sg[v] - 1]),从小到大取,使得(v)为根游戏状态为0的那条边,断了之后,由于断掉新边游戏状态是0,则这个状态给(u)为根的贡献是(1)

    使得(v)为根贡献为1的断边状态,子游戏中断边为0的状态可以转化为1,再填上断掉新边的状态是0,则这个对(u)的贡献变成了2

    以此类推,这种情况游戏状态就是(sg[v] + 1)

    #include <bits/stdc++.h>
    #define fi first
    #define se second
    #define pii pair<int,int>
    #define mp make_pair
    #define pb push_back
    #define space putchar(' ')
    #define enter putchar('
    ')
    #define MAXN 100005
    #define eps 1e-10
    //#define ivorysi
    using namespace std;
    typedef long long int64;
    typedef unsigned int u32;
    typedef double db;
    template<class T>
    void read(T &res) {
        res = 0;T f = 1;char c = getchar();
        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;
    struct node {
        int to,next;
    }E[MAXN * 2];
    int sumE,sg[MAXN],head[MAXN];
    void add(int u,int v) {
        E[++sumE].to = v;
        E[sumE].next = head[u];
        head[u] = sumE;
    }
    void dfs(int u,int fa) {
        sg[u] = 0;
        for(int i = head[u]; i ; i = E[i].next) {
    	int v = E[i].to;
    	if(v != fa) {
    	    dfs(v,u);
    	    sg[u] ^= (sg[v] + 1);
    	}
        }
    }
    void Solve() {
        read(N);
        int x,y;
        for(int i = 1 ; i < N ; ++i) {
    	read(x);read(y);
    	add(x,y);add(y,x);
        }
        dfs(1,0);
        if(sg[1]) puts("Alice");
        else puts("Bob");
    }
    int main() {
    #ifdef ivorysi
        freopen("f1.in","r",stdin);
    #endif
        Solve();
    }
    

    E - Jigsaw

    把连在地面上的高度设为正数,不连在地面上的高度设为负数
    然后一个点相当于一条边((l,r))
    相当于把整个图拆成负数点到正数点的若干路径
    只要判断一个弱联通图,负数点是否全为度数是否全负,正数点度数是否全正,然后至少有一个点点度不为0
    证明就是欧拉回路,两两匹配负数点和正数点,一定会有欧拉回路,断掉这些边就是答案

    #include <bits/stdc++.h>
    #define fi first
    #define se second
    #define pii pair<int,int>
    #define mp make_pair
    #define pb push_back
    #define space putchar(' ')
    #define enter putchar('
    ')
    #define MAXN 10005
    #define eps 1e-12
    //#define ivorysi
    using namespace std;
    typedef long long int64;
    typedef unsigned int u32;
    typedef double db;
    template<class T>
    void read(T &res) {
        res = 0;T f = 1;char c = getchar();
        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 g[405][405],f[405][405],ind[405],H,col[405],all;
    int N,A[100005],B[100005],C[100005],D[100005],cnt;
    bool vis[405],flag,has[405];
    void dfs(int u) {
        all += ind[u];
        if(ind[u]) flag = 1;
        vis[u] = 1;
        for(int i = 1 ; i <= 2 * H ; ++i) {
            if(f[u][i] && !vis[i]) dfs(i);
        }
    }
    void Solve() {
        read(N);read(H);
        for(int i = 1 ; i <= N ; ++i) {
            read(A[i]);read(B[i]);read(C[i]);read(D[i]);
            int s,t;
            if(C[i]) s = C[i];
            else s = A[i] + H;
            if(D[i]) t = D[i] + H;
            else t = B[i];
            g[s][t]++;ind[t]++;ind[s]--;
            f[s][t]++;f[t][s]++;
            has[s] = has[t] = 1;
        }
        for(int i = 1 ; i <= H ; ++i) {
            if(ind[i] < 0) {puts("NO");return;}
        }
        for(int i = H + 1 ; i <= 2 * H ; ++i) {
            if(ind[i] > 0) {puts("NO");return;}
        }
        for(int i = 1 ; i <= 2 * H ; ++i) {
            if(!has[i]) continue;
            if(!vis[i]) {
                flag = 0;
                dfs(i);
                if(all != 0 || !flag) {puts("NO");return;}
            }
        }
        puts("YES");
    }
    int main() {
    #ifdef ivorysi
    	freopen("f1.in","r",stdin);
    #endif
        Solve();
    }
    

    F - Zigzag

    dp[i][j][mask]表示第i条边走了第j步,左边界是什么
    根据限制和每一步的选择修改左边界即可
    复杂度(O(n^{2}2^{n}))

    #include <bits/stdc++.h>
    #define fi first
    #define se second
    #define pii pair<int,int>
    #define mp make_pair
    #define pb push_back
    #define space putchar(' ')
    #define enter putchar('
    ')
    #define MAXN 200005
    #define eps 1e-12
    //#define ivorysi
    using namespace std;
    typedef long long int64;
    typedef unsigned int u32;
    typedef double db;
    template<class T>
    void read(T &res) {
        res = 0;T f = 1;char c = getchar();
        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,K;
    int A[405],B[405],C[405],w[25][25];
    int dp[2][21][(1 << 19) + 5];
    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 update(int &x,int y) {
        x = inc(x,y);
    }
    int lowbit(int x) {
        return x & (-x);
    }
    void Solve() {
        read(N);read(M);read(K);
        memset(w,-1,sizeof(w));
        for(int i = 1 ; i <= K ; ++i) {
            read(A[i]);read(B[i]);read(C[i]);
            w[A[i]][B[i]] = C[i];
        }
        int cur = 0;
        dp[0][1][0] = 1;
        for(int i = 1 ; i <= M ; ++i) {
            for(int j = 1 ; j < N ; ++j) {
                for(int s = 0 ; s < (1 << N - 1) ; ++s) {
                    if(!dp[cur][j][s]) continue;
                    if(w[i][j] != 1 && !(s >> (j - 1) & 1)) update(dp[cur][j + 1][s],dp[cur][j][s]);
                    if(w[i][j] != 0) {
                        if(s >> (j - 1) & 1) update(dp[cur][j + 1][s],dp[cur][j][s]);
                        else {
                            int t = s - (s & (1 << j) - 1);
                            t -= t & (-t);
                            t ^= (1 << j - 1);
                            t += s & (1 << j) - 1;
                            update(dp[cur][j + 1][t],dp[cur][j][s]);
                        }
                    }
                }
            }
            memset(dp[cur ^ 1],0,sizeof(dp[cur ^ 1]));
            for(int s = 0 ; s < (1 << N - 1) ; ++s) dp[cur ^ 1][1][s] = dp[cur][N][s];
            cur ^= 1;
        }
        int ans = 0;
        for(int s = 0 ; s < (1 << N - 1) ; ++s) ans = inc(ans,dp[cur][1][s]);
        out(ans);enter;
    }
    int main() {
    #ifdef ivorysi
    	freopen("f1.in","r",stdin);
    #endif
        Solve();
    }
    
  • 相关阅读:
    策略模式
    装饰模式VS代理模式
    BufferedInputSream实现原理
    从字节码角度分析重载与重写
    函数sprintf真好用
    算法时间复杂度
    二项分布(Binomial Distribution)
    numpy中的tile函数
    图像缩放算法(最临近点插值算法、双线性内插值算法、双立方插值算法)
    C++ 类中成员函数的属性
  • 原文地址:https://www.cnblogs.com/ivorysi/p/10554163.html
Copyright © 2011-2022 走看看