zoukankan      html  css  js  c++  java
  • 【AtCoder】Tenka1 Programmer Contest 2019

    Tenka1 Programmer Contest 2019

    C - Stones

    题面大意:有一个01序列,改变一个位置上的值花费1,问变成没有0在1右边的序列花费最少多少

    直接枚举前i个都变成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 eps 1e-10
    #define MAXN 200005
    //#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;
    char s[MAXN];
    int sum[MAXN];
    void Solve() {
        read(N);
        scanf("%s",s + 1);
        for(int i = 1 ; i <= N ; ++i) {
    	sum[i] = sum[i - 1];
    	if(s[i] == '#') sum[i]++;
        }
        int ans = N;
        for(int i = 0 ; i <= N ; ++i) {
    	ans = min(ans,sum[i] + N - i - (sum[N] - sum[i]));
        }
        out(ans);enter;
    }
    int main() {
    #ifdef ivorysi
        freopen("f1.in","r",stdin);
    #endif
        Solve();
    }
    

    D - Three Colors

    大意:将数分到三个标号为123的集合,要求三个集合能构成三角形

    题解:也就是(R + B + G = S)满足(G,R,B < frac{S}{2})

    不合法的情况就是有一个集合大于等于(frac{S}{2})的方案,对于等于(frac{S}{2})再用一个dp去重即可

    #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 eps 1e-10
    #define MAXN 200005
    //#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 = 998244353;
    int N;
    int a[305],S;
    int dp[305][90005],f[90005];
    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 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 Solve() {
        read(N);
        for(int i = 1 ; i <= N ; ++i) {
    	read(a[i]);
    	S += a[i];
        }
        dp[0][0] = 1;
        f[0] = 1;
        for(int i = 1 ; i <= N ; ++i) {
    	for(int j = S ; j >= 0 ; --j) {
    	    update(dp[i][j],mul(2,dp[i - 1][j]));
    	    if(j >= a[i]) {
    		update(dp[i][j],dp[i - 1][j - a[i]]);
    		update(f[j],f[j - a[i]]);
    	    }
    	}
        }
        int ans = fpow(3,N);
        for(int j = 0 ; j <= S ; ++j) {
    	if(j * 2 >= S) {
    	    update(ans,MOD - mul(3,dp[N][j]));
    	}
        }
        if(S % 2 == 0) {
    	update(ans,mul(f[S / 2],3));
        }
        out(ans);enter;
    }
    int main() {
    #ifdef ivorysi
        freopen("f1.in","r",stdin);
    #endif
        Solve();
    }
    

    E - Polynomial Divisors

    大意:给定多项式求多项式取所有整数值时都能被整除的质数

    盲猜肯定要么是所有系数的gcd的质因数要么就小于最高次项,然后判解不会就直接暴力,以为数据造不满然后被卡死了,atc的数据还是强

    事实上判解的话只要判这个多项式在modp意义下是否是多项式(x^{p} - x)的倍数即可

    充分性显然(费马小定理)

    必要性合法的式子会含有(x(x - 1)(x - 2)..(x - (p - 1))),然后这个东西在modp意义下是(x^{p} - x)相等,如果不是全等的话,必然有一个小于等于p - 1的多项式是有p个根,这不存在

    #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 eps 1e-10
    #define MAXN 10005
    //#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);
    }
    set<int> S;
    int g;
    int N,a[MAXN],b[MAXN],c[MAXN];
    int prime[MAXN],tot;
    bool nonprime[MAXN];
    int gcd(int a,int b) {
        return  b == 0 ? a : gcd(b,a % b);
    }
    void Solve() {
        read(N);
        for(int i = N ; i >= 0 ; --i) {
    	read(a[i]);
    	g = gcd(g,abs(a[i]));
        }
        for(int i = 2 ; i <= g / i ; ++i) {
    	if(g % i == 0) {
    	    S.insert(i);
    	    while(g % i == 0) g /= i;
    	}
        }
        if(g > 1) S.insert(g);
        for(int i = 2 ; i <= 10000 ; ++i) {
    	if(!nonprime[i]) {
    	    prime[++tot] = i;
    	}
    	for(int j = 1 ; j <= tot ; ++j) {
    	    if(1LL * i * prime[j] > 10000) break;
    	    nonprime[i * prime[j]] = 1;
    	    if(i % prime[j] == 0) break;
    	}
        }
        for(int i = 1 ; i <= tot ; ++i) {
    	if(prime[i] > N) break;
    	int p = prime[i];
    	if(S.find(p) != S.end()) continue;
    	memset(b,0,sizeof(b));
    	memset(c,0,sizeof(c));
    	bool flag = 1;
    	for(int i = N ; i >= 0 ; --i) {
    	    b[i] = (a[i] + c[i]) % p;
    	    if(i >= p) {
    		c[1 + i - p] += b[i];
    		c[1 + i - p] %= p;
    	    }
    	    else if(b[i]){
    		flag = 0;break;
    	    }
    	}
    	if(flag) S.insert(p);
        }
        for(auto t : S) {
    	out(t);enter;
        }
    }
    int main() {
    #ifdef ivorysi
        freopen("f1.in","r",stdin);
    #endif
        Solve();
    }
    

    F - Banned X

    大意:找到一个长度为N序列只含0,1,2,求其中任意一段连续的和不为x的答案

    首先统计所有和小于x的答案

    然后就是如果x为奇数,我只选2且序列总和大于x的答案

    然后就是,因为我每一段的和都不是x,每次增加是1或2,那么肯定存在一个和是(X - 1)的前缀和

    此时我只能选2,如果序列开头第一个不为0的数是2,那么我可以删掉这个2,往后继续加一个2,直到我删掉时遇到了一个1

    所以我们枚举i个2+1个1的序列,枚举构成X - 1所用的序列长度,之后只能往后加不超过i个2即可

    #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 eps 1e-10
    #define MAXN 10005
    //#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 = 998244353;
    int N,X;
    int dp[3005][6005],fac[6005],invfac[6005];
    int f[3005];
    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 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;
    }
    int C(int n,int m) {
        if(n < m) return 0;
        return mul(fac[n],mul(invfac[m],invfac[n - m]));
    }
    void Solve() {
        read(N);read(X);
        dp[0][0] = 1;
        fac[0] = 1;
        for(int i = 1 ; i <= 2 * N ; ++i) fac[i] = mul(fac[i - 1],i);
        invfac[2 * N] = fpow(fac[2 * N],MOD - 2);
        for(int i = 2 * N - 1 ; i >= 0 ; --i) {
    	invfac[i] = mul(invfac[i + 1],i + 1);
        }
        int ans = 0;
        for(int i = 1 ; i <= N ; ++i) {
    	for(int j = 2 * i ; j >= 1 ; --j) {
    	    if(j >= 2) update(dp[i][j],dp[i - 1][j - 2]);
    	    if(j >= 1) update(dp[i][j],dp[i - 1][j - 1]);
    	}
        }
        for(int i = 0 ; i <= N ; ++i) {
    	for(int j = 0 ; j <= 2 * i ; ++j) {
    	    if(j < X) update(ans,mul(dp[i][j],C(N,i)));
    	}
        }
        for(int i = 1 ; i < N ; ++i) {
    	int t = i * 2 + 1;
    	if(t >= X) break;
    	for(int j = 0 ; j <= N ; ++j) {
    	    if(i + j + 2 <= N) {
    		update(f[i + j + 2],dp[j][X - 1 - t]);
    		if(i + j + i + 2 <= N) update(f[i + j + i + 2],MOD - dp[j][X - 1 - t]);
    	    }
    	}
        }
        for(int i = 1 ; i <= N ; ++i) f[i] = inc(f[i],f[i - 1]);
        for(int i = 1 ; i <= N ; ++i) {
    	update(ans,mul(f[i],C(N,i)));
        }
        if(X & 1) {
    	for(int i = 1 ; i <= N ; ++i) {
    	    if(i * 2 > X) update(ans,C(N,i));
    	}
        }
        out(ans);enter;
    }
    int main() {
    #ifdef ivorysi
        freopen("f1.in","r",stdin);
    #endif
        Solve();
    }
    
  • 相关阅读:
    javascript 的原型与原型链的理解
    mysql 复制原理与实践
    mysql 数据库备份的多种方式
    mysql 事务中如果有sql语句出错,会导致自动回滚吗?
    【原】ios下比较完美的单例模式,已验证
    【原/转】ios指令集以及基于指令集的app包压缩策略
    【原】多线程编程中临界区与互斥锁的区别
    【转】Windows的多线程编程,C/C++
    【转】c++中Vector等STL容器的自定义排序
    【转】牛人整理分享的面试知识:操作系统、计算机网络、设计模式、Linux编程,数据结构总结
  • 原文地址:https://www.cnblogs.com/ivorysi/p/10762468.html
Copyright © 2011-2022 走看看