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

    C - Good Sequence

    题解

    用个map愉悦一下就好了

    代码

    #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('
    ')
    #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;
    int a[MAXN],ans;
    map<int,int> zz;
    void Init() {
        read(N);
        for(int i = 1 ; i <= N ; ++i) {read(a[i]);zz[a[i]] += 1;}
        sort(a + 1,a + N + 1);
        N = unique(a + 1,a + N + 1) - a - 1;
    }
    void Solve() {
        for(int i = 1 ; i <= N ; ++i) {
    	if(zz[a[i]] < a[i]) ans += zz[a[i]];
    	else ans += zz[a[i]] - a[i];
        }
        out(ans);enter;
    }
    int main() {
    #ifdef ivorysi
        freopen("f1.in","r",stdin);
    #endif
        Init();
        Solve();
    }
    

    D - FT Robot

    如果经过了奇数个T,那么原来在x轴上走,后来肯定在y轴上走,原来y轴变为x轴
    如果偶数个T,那么保持原来的轴不变
    我们会选定一个方向使得在这个方向上走后面的F的个数
    这个可以用一个简单的背包(加上bitset优化一下)实现,注意在序列最前的F手动走完,因为无法改成X轴负方向

    代码

    #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('
    ')
    #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,x,y,s,t;
    char str[8005];
    vector<int> dir[2];
    bitset<16005> f[2];
    bool cmp(int a,int b) {
        return a > b;
    }
    void Solve() {
        scanf("%s",str + 1);read(x);read(y);
        N = strlen(str + 1);
        int d = 0;
        s = 0,t = 0;
        int p = 1;
        while(p <= N && str[p] == 'F') {++s;++p;}
        int cnt = 0;
        for(int i = p ; i <= N ; ++i) {
    	if(str[i] == 'T') {
    	    if(cnt) dir[d].pb(cnt);
    	    d ^= 1;cnt = 0;
    	}
    	else {++cnt;}
        }
        if(cnt) dir[d].pb(cnt);
        if(abs(s - x) > N) {puts("No");return;}
        int cur = 0;
        f[cur].reset();
        f[cur][8000] = 1;
        for(auto k : dir[0]) {
    	f[cur ^ 1].reset();
    	f[cur ^ 1] = (f[cur] << k) | (f[cur] >> k);
    	cur ^= 1;
        }
        if(!f[cur][8000 + abs(s - x)]) {puts("No");return;}
        cur = 0;
        f[cur].reset();
        f[cur][8000] = 1;
        for(auto k : dir[1]) {
    	f[cur ^ 1].reset();
    	f[cur ^ 1] = (f[cur] << k) | (f[cur] >> k);
    	cur ^= 1;
        }
        if(!f[cur][8000 + abs(t - y)]) {puts("No");return;}
        puts("Yes");
    }
    int main() {
    #ifdef ivorysi
        freopen("f1.in","r",stdin);
    #endif
        Solve();
    }
    

    E-Prefix-free Game

    给每个可以走的点的sg函数简单推一下,从第(L - 1)层开始归纳
    很容易发现sg函数是lowbit(L - dep)

    代码

    #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('
    ')
    #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 son[MAXN][2],N,rt = 1,Ncnt = 1;
    int64 L,dep[MAXN];
    char s[MAXN];
    int64 lowbit(int64 x) {
        return x & -x;
    }
    void Insert(char *str) {
        int len = strlen(str + 1);
        int p = rt;
        for(int i = 1 ; i <= len ; ++i) {
    	if(!son[p][str[i] - '0']) {
    	    son[p][str[i] - '0'] = ++Ncnt;
    	    dep[Ncnt] = dep[p] + 1;
    	}
    	p = son[p][str[i] - '0'];
        }
    }
    void Solve() {
        read(N);read(L);
        for(int i = 1 ; i <= N ; ++i) {
    	scanf("%s",s + 1);
    	Insert(s);
        }
        int64 ans = 0;
        for(int i = 1 ; i <= Ncnt ; ++i) {
    	if((son[i][0] == 0 && son[i][1] != 0) || (son[i][0] != 0 && son[i][1] == 0)) {
    	    ans ^= lowbit(L - dep[i]);
    	}
        }
        if(ans) puts("Alice");
        else puts("Bob");
    }
    int main() {
    #ifdef ivorysi
        freopen("f1.in","r",stdin);
    #endif
        Solve();
    }
    

    F - Squirrel Migration

    第一个结论就推不出来QAQ
    就是考虑一条边,边断掉分成两个子树是(x,y),这条边最多被经过(2min{siz[x],siz[y]})

    考虑有两个重心(也就是断开一条边可以分成两个大小为(N / 2)的子树)
    肯定可以构造合法的解,方案数就是((frac{N}{2}!)^2)

    有一个重心也是有解的,就是把所有的儿子从大到小排序
    把最大的放在第一个,然后把剩下从小到大放,重心到它自己即可
    这是一个合法解
    那么我们可以知道,满足条件的答案一定是重心随便放,断掉重心后,剩下的点必须不选自己所在的树里的点

    我们可以容斥做,用(f[k])选了k个点,且这k个点能到达的点都是自己子树中的点,类似树背包那样转移
    答案就是(sum_{i = 0}^{N - 1} (-1)^{i}f[i] cdot (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('
    ')
    #define space putchar(' ')
    #define eps 1e-8
    #define mo 974711
    #define MAXN 5005
    //#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;
    struct node {
        int to,next;
    }E[MAXN * 2];
    int head[MAXN],sumE,siz[MAXN],son[MAXN];
    int C[MAXN][MAXN],fac[MAXN],val[MAXN],tot,f[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) {
        E[++sumE].next = head[u];
        E[sumE].to = v;
        head[u] = sumE;
    }
    void dfs(int u,int fa) {
        siz[u] = 1;
        for(int i = head[u] ; i ; i = E[i].next) {
    	int v = E[i].to;
    	if(v != fa) {
    	    dfs(v,u);
    	    siz[u] += siz[v];
    	    son[u] = max(son[u],siz[v]);
    	}
        }
        son[u] = max(son[u],N - siz[u]);
    }
    void Init() {
        read(N);
        int x,y;
        for(int i = 1 ; i < N ; ++i) {
    	read(x);read(y);
    	add(x,y);add(y,x);
        }
        C[0][0] = 1;
        for(int i = 1 ; i <= N ; ++i) {
    	C[i][0] = 1;
    	for(int j = 1 ; j <= N ; ++j) {
    	    C[i][j] = inc(C[i - 1][j],C[i - 1][j - 1]);
    	}
        }
        fac[0] = 1;
        for(int i = 1 ; i <= N ; ++i) fac[i] = mul(fac[i - 1],i);
    }
    void Solve() {
        dfs(1,0);
        int g = 1;
        for(int i = 2 ; i <= N ; ++i) {
    	if(son[i] < son[g]) g = i;
        }
        if(N % 2 == 0 && son[g] == N / 2) {
    	out(mul(fac[N / 2],fac[N / 2]));enter;return;
        }
        for(int i = head[g] ; i ; i = E[i].next) {
    	int v = E[i].to;
    	if(siz[v] < siz[g]) val[++tot] = siz[v];
        }
        if(g != 1) val[++tot] = N - siz[g];
        int s = 0;f[0] = 1;
        for(int i = 1 ; i <= tot ; ++i) {
    	for(int t = s + val[i] ; t >= 0 ; --t) {
    	    for(int j = 1 ; j <= val[i] ; ++j) {
    		if(j > t) break;
    		f[t] = inc(f[t],mul(mul(f[t - j],C[val[i]][j]),mul(C[val[i]][j],fac[j])));
    	    }
    	}
    	s += val[i];
        }
        int t = 1,ans = 0;
        for(int i = 0 ; i <= N - 1; ++i) {
    	ans = inc(ans,mul(mul(t,f[i]),fac[N - i]));
    	t = mul(t,MOD - 1);
        }
        out(ans);enter;
    }
    int main() {
    #ifdef ivorysi
        freopen("f1.in","r",stdin);
    #endif
        Init();
        Solve();
    }
    
  • 相关阅读:
    ES6模块开发+单文件组件
    Vue路由学习
    Vuex学习
    Vue组件
    Vue事件处理
    Git下载前后端代码步骤
    小黑记事本
    简单计算器
    ubuntu的基础命令
    拓扑排序以及求解关键路径
  • 原文地址:https://www.cnblogs.com/ivorysi/p/10171974.html
Copyright © 2011-2022 走看看