zoukankan      html  css  js  c++  java
  • 【AtCoder】ARC099题解

    C - Minimization

    每次操作必然包含一个1
    枚举第一次操作的位置计算两边即可

    代码

    #include <bits/stdc++.h>
    #define fi first
    #define se second
    #define pii pair<int,int>
    #define space putchar(' ')
    #define enter putchar('
    ')
    #define MAXN 100005
    //#define ivorysi
    using namespace std;
    typedef long long int64;
    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,K;
    int a[MAXN],pos[MAXN];
    int C(int x) {
        return x % (K - 1) == 0 ? x / (K - 1) : x / (K - 1) + 1;
    }
    void Solve() {
        read(N);read(K);
        for(int i = 1 ; i <= N ; ++i) {read(a[i]);pos[a[i]] = i;}
        int ans = N;
        for(int i = 1 ; i <= N ; ++i) {
    	if(i + K - 1 >= pos[1]) {
    	    ans = min(ans,C(i - 1) + C(N - min((i + K - 1),N)) + 1);
    	}
        }
        out(ans);enter;
    }
    int main() {
    #ifdef ivorysi
        freopen("f1.in","r",stdin);
    #endif
        Solve();
    }
    

    D - Snuke Numbers

    我们对于N 只要能求出(f(N + 1))((f(x))表示大于等于(x)的数中(frac{x}{S(x)})最小的那个)
    那么就能不断找到下一个数了

    怎么求呢,我们可以认为一个可以被取到的数一定是x的一段前缀,加上中间某个数修改,后面的所有数都改成9

    因为999999...9999是一个合法的数,那么可以认为(f(x))的位数和(x)一定相同

    如果我们找到一个数(a),它的第d位与x不同,且它后面不都是9,那么我们可以把第d位-1,后面全部修改成9

    所以我们找的数的数目有限,都找出来找最小的(frac{x}{S(x)})即可

    代码

    #include <bits/stdc++.h>
    #define fi first
    #define se second
    #define pii pair<int,int>
    #define space putchar(' ')
    #define enter putchar('
    ')
    #define MAXN 100005
    //#define ivorysi
    using namespace std;
    typedef long long int64;
    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 K,t[25],tot,cnt,s[10005];
    int64 L[10005],p[25],b[25];
    int S(int64 x) {
        int res = 0;
        while(x) {res += x % 10;x /= 10;}
        return res;
    }
    
    int64 f(int64 x) {
        tot = 0;cnt = 0;int64 h = x;
        while(h) {t[++tot] = h % 10;h /= 10;}
        int64 num = 0;
        for(int i = tot ; i >= 1 ; --i) {
    	for(int j = t[i] ; j <= 9 ; ++j) {
    	    int64 tmp = num + j * b[i - 1] + p[i - 1];
    	    if(tmp >= x) L[++cnt] = tmp;
    	}
    	num = num + t[i] * b[i - 1];
        }
        
        for(int i = 1 ; i <= cnt ; ++i) s[i] = S(L[i]);
        int r = 1;
        for(int i = 2 ; i <= cnt ; ++i) {
    	int64 h = L[i] * s[r] - L[r] * s[i];
    	if(h < 0) r = i;
    	else if(h == 0 && L[i] < L[r]) r = i; 
        }
        return L[r];
    }
    void Solve() {
        read(K);
        int64 N = 1;
        p[1] = 9;
        for(int i = 2 ; i <= 16 ; ++i) p[i] = p[i - 1] * 10 + 9;
        b[0] = 1;
        for(int i = 1 ; i <= 16 ; ++i) b[i] = b[i - 1] * 10;
        while(K--) {
    	out(N);enter;
    	N = f(N + 1);
        }
    }
    int main() {
    #ifdef ivorysi
        freopen("f1.in","r",stdin);
    #endif
        Solve();
    }
    

    E - Independence

    反图必然是个二分图,不然则无解

    我们希望知道哪些分的情况可以达到,就直接把一个二分图的联通块拿出来,做分组背包即可

    代码

    #include <bits/stdc++.h>
    #define fi first
    #define se second
    #define pii pair<int,int>
    #define space putchar(' ')
    #define enter putchar('
    ')
    #define MAXN 100005
    #define mp make_pair
    //#define ivorysi
    using namespace std;
    typedef long long int64;
    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 g[705][705];
    struct node {
        int to,next;
    }E[1000005];
    int sumE,head[705],tot,col[705],que[705],qr;
    pii conn[705];
    bool f[2][705];
    void add(int u,int v) {
        E[++sumE].next = head[u];
        E[sumE].to = v;
        head[u] = sumE;
    }
    bool dfs(int u) {
        if(col[u] == -1) col[u] = 0;
        que[++qr] = u;
        for(int i = head[u] ; i ; i = E[i].next) {
    	int v = E[i].to;
    	if(col[v] == col[u]) return false;
    	else if(col[v] == -1) {
    	    col[v] = col[u] ^ 1;
    	    if(!dfs(v)) return false;
    	}
        }
        return true;
    }
    void Solve() {
        read(N);read(M);
        int u,v;
        for(int i = 1 ; i <= M ; ++i) {
    	read(u);read(v);
    	g[u][v] = g[v][u] = 1;
        }
        for(int i = 1 ; i <= N ; ++i) {
    	for(int j = i + 1 ; j <= N ; ++j) {
    	    if(!g[i][j]) {add(i,j);add(j,i);}
    	}
        }
        memset(col,-1,sizeof(col));
        for(int i = 1 ; i <= N ; ++i) {
    	if(col[i] == -1) {
    	    qr = 0;
    	    if(!dfs(i)) {puts("-1");return;}
    	    int cnt[2] = {0,0};
    	    for(int j = 1 ; j <= qr ; ++j) cnt[col[que[j]]]++;
    	    conn[++tot] = mp(cnt[0],cnt[1]);
    	}
        }
        int cur = 0;
        f[0][0] = 1;
        for(int i = 1 ; i <= tot ; ++i) {
    	memset(f[cur ^ 1],0,sizeof(f[cur ^ 1]));
    	for(int j = N ; j >= 0 ; --j) {
    	    if(j >= conn[i].fi) f[cur ^ 1][j] |= f[cur][j - conn[i].fi];
    	    if(j >= conn[i].se) f[cur ^ 1][j] |= f[cur][j - conn[i].se];
    	}
    	cur ^= 1;
        }
        int ans = N * N;
        for(int i = 0 ; i <= N ; ++i) {
    	if(f[cur][i]) {
    	    ans = min(i * (i - 1) / 2 + (N - i) * (N - i - 1) / 2,ans);
    	}
        }
        out(ans);enter;
    }
    int main() {
    #ifdef ivorysi
        freopen("f1.in","r",stdin);
    #endif
        Solve();
    }
    

    F - Eating Symbols Hard

    一道神奇的题

    我们把操作S构成的A数组用一个多项式表示出来
    (t(S) = sum_{i = -10^9}^{10^9} A_{i}X^{i})
    如果往S前面添加一个字符的话
    (t<(S) = t(S)X^{-1})
    (t>(S) = t(S)X)
    (t+(S) = t(S) + 1)
    (t-(S) = t(S) - 1)
    那么我们对于最终的序列求一个哈希值c,如果一段区间操作后的结果和c一样的话就有
    (t_{S_i}t_{S_{i + 1}}...t_{S_j}(0) = c)
    由于这些操作可逆,可以一层一层拆开
    可以得到
    (t_{S_N}^{-1}...t_{S_i}^{-1}t_{S_i}t_{S_{i + 1}}...t_{S_j}(0) = t_{S_N}^{-1}...t_{S_i}^{-1}(c))
    那么我们可以得到
    (t_{S_N}^{-1}...t_{S_{j + 1}}^{-1} (0) = t_{S_N}^{-1}...t_{S_{i}}^{-1}(c))
    这个后缀积可以线性处理出来,维护未知数前的系数即可

    然后就是愉快的用map查询了

    那么,冲突怎么考虑?题解说是冲突的概率在2N/模数大小,让用6个,然而我写的不优美,T掉了,改成5个卡着时限A了,感觉用不上太多也是对的啊

    代码

    #include <iostream>
    #include <algorithm>
    #include <cstdio>
    #include <cstring>
    #include <queue>
    #include <cmath>
    #include <map>
    #define enter putchar('
    ')
    #define space putchar(' ')
    #define mp make_pair
    #define pb push_back
    #define fi first
    #define se second
    #define pii pair<int,int>
    #define eps 1e-7
    #define MAXN 250005
    #define MOD 999999137
    //#define ivorysi
    using namespace std;
    typedef long long int64;
    typedef double db;
    typedef vector<int> poly;
     
    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) {putchar('-');x = -x;}
    	if(x >= 10) {
    		out(x / 10);
    	}
    	putchar('0' + x % 10);
    }
    int B[] = {0,823,727,401,271,571};
    int InvB[10];
    int f[8][MAXN],g[8][MAXN],N,h[8][MAXN];
    char s[MAXN];
    map<int,int> MK[8];
     
     
    int mul(int a,int b) {
    	return 1LL * a * b % MOD;
    }
    int inc(int a,int b) {
    	return a + b >= MOD ? a + b - MOD : a + b;
    }
    void update(int &x,char c,int id) {
    	if(c == '<') x = mul(x,InvB[id]);
    	else if(c == '>') x = mul(x,B[id]);
    	else if(c == '+') x = inc(x,1);
    	else x = inc(x,MOD - 1);
    }
    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() {
    	for(int i = 1 ; i <= 5 ; ++i) InvB[i] = fpow(B[i],MOD - 2);
    	read(N);
    	scanf("%s",s + 1);
    	int c[10] = {0};
    	for(int k = 1 ; k <= 5 ; ++k) {
    		for(int i = N ; i >= 1 ; --i) {
    			update(c[k],s[i],k);
    		}
    	}
    	for(int k = 1 ; k <= 5 ; ++k) h[k][N + 1] = 1,g[k][N + 1] = c[k],MK[k][0] += 1;
    	int64 ans = 0;
    	for(int i = N ; i >= 1 ; --i) {
    		int add = N - i + 1;
    		for(int k = 1 ; k <= 5 ; ++k) {
    			if(s[i] == '<') {
    				g[k][i] = inc(g[k][i + 1],MOD - mul(h[k][i + 1],c[k]));
    				h[k][i] = mul(h[k][i + 1],B[k]);
    				g[k][i] = inc(g[k][i],mul(h[k][i],c[k]));
    				f[k][i] = f[k][i + 1];		
    			}
    			else if(s[i] == '>') {
    				g[k][i] = inc(g[k][i + 1],MOD - mul(h[k][i + 1],c[k]));
    				h[k][i] = mul(h[k][i + 1],InvB[k]);
    				g[k][i] = inc(g[k][i],mul(h[k][i],c[k]));
    				f[k][i] = f[k][i + 1];
    			}
    			else if(s[i] == '+') {
    				h[k][i] = h[k][i + 1];
    				g[k][i] = inc(g[k][i + 1],MOD - h[k][i]);
    				f[k][i] = inc(f[k][i + 1],MOD - h[k][i]);
    			}
    			else {
    				h[k][i] = h[k][i + 1];
    				g[k][i] = inc(g[k][i + 1],h[k][i]);
    				f[k][i] = inc(f[k][i + 1],h[k][i]);
    			}
    			add = min(add,MK[k][g[k][i]]);
    			MK[k][f[k][i]] += 1;
    		}
    		ans += add;
    	}
    	out(ans);enter;	
    }
    int main() {
    #ifdef ivorysi
    	freopen("f1.in","r",stdin);
    #endif
    	Solve();
    	return 0;
    }
    
  • 相关阅读:
    Eclipse 远程调试
    大数据处理方法bloom filter
    sicily 1259 Sum of Consecutive Primes
    sicily 1240. Faulty Odometer
    sicily 1152 简单马周游 深度优先搜索及回溯算法
    sicily 1050 深度优先搜索解题
    sicily 1024 邻接矩阵与深度优先搜索解题
    sicily 1156 二叉树的遍历 前序遍历,递归,集合操作
    sicily 1443 队列基本操作
    sicily 1006 team rankings 枚举解题
  • 原文地址:https://www.cnblogs.com/ivorysi/p/9812586.html
Copyright © 2011-2022 走看看