zoukankan      html  css  js  c++  java
  • 2019 ICPC Asia Yinchuan Regional

    2019 ICPC Asia Yinchuan Regional

    (A. Girls Band Party)

    (B. So Easy)
    (n)(n)列分别加上一个(ge 0)的数,已知其他位置的数,求(x)(y)列处的数是多少
    每行每列全都减去当前行或列最小的那个数,第(x)行减去的值和第(y)列减去的值的和就是答案
    相当于原来操作的逆操作

    //#pragma GCC optimize("O3")
    //#pragma comment(linker, "/STACK:1024000000,1024000000")
    #include<bits/stdc++.h>
    using namespace std;
    function<void(void)> ____ = [](){ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);};
    const int MAXN = 1111;
    int n,A[MAXN][MAXN];
    void solve(){
        cin >> n;
        int x,y,ret=0;
        for(int i = 1; i <= n; i++) for(int j = 1; j <= n; j++){
            cin >> A[i][j];
            if(A[i][j]==-1) x = i, y = j;
        }
        for(int i = 1; i <= n; i++){
            int minn = 1e7;
            for(int j = 1; j <= n; j++) if(A[i][j]>=0) minn = min(minn,A[i][j]);
            for(int j = 1; j <= n; j++) A[i][j] -= minn;
            if(i==x) ret+=minn;
        }
        for(int i = 1; i <= n; i++){
            int minn = 1e7;
            for(int j = 1; j <= n; j++) if(A[j][i]>=0) minn = min(minn,A[j][i]);
            for(int j = 1; j <= n; j++) A[j][i] -= minn;
            if(i==y) ret+=minn;
        }
        cout << ret << endl;
    }
    int main(){
        ____();
        solve();    
        return 0;
    }
    

    (C. Image Processing)

    (D. Easy Problem)

    [计算sum (a_1cdot a_2 cdot a_3 cdots a_n)^k 其中gcd(a_1,a_2,a_3,cdots,a_n)=d且a_ile m ]

    转化一下,就是计算:

    [(d^k)^nsum (b_1cdot b_2 cdot b_3 cdots b_n)^k 其中gcd(b_1,b_2,b_3,cdots,b_n)=1且b_ile lfloor frac{m}{d} floor ]

    考虑如何计算(sum (x_1cdot x_2cdot x_3cdots x_n)^k),其中(1le x_ile m)
    (sum (x_1cdot x_2cdot x_3cdots x_n)^k = sum (x_1^kcdot x_2^kcdot x_3^kcdots x_n^k) = (sum_{i=1}^{m}i^k)^n)
    然后我们需要去掉(gcd(b_1,b_2,b_3,cdots,b_n) e 1)的情况,这是个和约数相关的容斥原理,容斥系数就是莫比乌斯函数
    所以最后可以得到:

    [resault = (d^k)^ncdot sum_{i=1}^{lfloor frac{m}{d} floor} mu (i)((sum_{j=1}^{lfloor frac{m}{id} floor}j^k)(i^k))^n ]

    内部可以用前缀和预处理加上快速幂复杂度大概是(O(Tmlog(MOD)))
    注意这里的模数(59964251)不是质数,大数幂的时候需要用扩展欧拉定理

    
    //#pragma GCC optimize("O3")
    //#pragma comment(linker, "/STACK:1024000000,1024000000")
    #include<bits/stdc++.h>
    using namespace std;
    function<void(void)> ____ = [](){ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);};
    const int MAXN = 1e5+7;
    using LL = int_fast64_t;
    const LL MOD = 59964251;
    const LL phi = 59870352;
    char n[MAXN];
    LL m, d, k, pre[MAXN];
    int mu[MAXN],npm[MAXN];
    vector<int> prime;
    LL qpow(LL a, LL b){
        LL ret = 1;
        while(b){
            if(b&1) ret = ret * a % MOD;
            b >>= 1;
            a = a * a % MOD;
        }
        return ret;
    }
    void preprocess(){
        mu[1] = 1;
        for(int i = 2; i < MAXN; i++){
            if(!npm[i]) prime.emplace_back(i), mu[i] = -1;
            for(int j = 0; j < (int)prime.size(); j++){
                if(i*prime[j]>=MAXN) break;
                npm[i*prime[j]] = true;
                mu[i*prime[j]] = -mu[i];
                if(i%prime[j]==0){
                    mu[i*prime[j]] = 0;
                    break;
                }
            }
        }
    }
    void solve(){
        cin >> n >> m >> d >> k;
        LL pw = 0;
        for(int i = 0, len = strlen(n); i < len; i++) pw = (pw * 10 + n[i]-'0') % phi;     //扩展欧拉定理
        pw += phi;
        k = k % phi + phi;
        for(int i = 1; i <= m; i++) pre[i] = (pre[i-1] + qpow(i,k)) % MOD;
        LL ret = 0;
        for(int i = 1; i <= m / d; i++) ret = (ret + mu[i] * qpow((pre[m/(i*d)]*qpow(i,k))%MOD,pw)) % MOD;
        ret = ret * qpow(qpow(d,k),pw) % MOD;
        if(ret<0) ret += MOD;
        cout << ret << endl;
    }
    int main(){
        ____();
        int T;
        preprocess();
        for(cin >> T; T; T--) solve();
        return 0;
    }
    

    (E. XOR Tree)

    (F. Function!)

    [计算 sum_{a=2}^{n}(asum_{b=a}^{n}lfloorlog_{a}b floor),nle 10^{12} ]

    发现(a>lfloor sqrt{n} floor)时,后面的和式变成了(asum_{b=a}^{n}1=acdot(n-a+1))
    所以而在(sqrt{n})之前的可以枚举(lfloorlog_ab floor)来计算,式子变成:

    [sum_{a=2}^{lfloor sqrt{n} floor}(asum_{b=a}^{n} lfloorlog_{a}b floor)+sum_{a=lfloorsqrt{n} floor +1}^{n}(acdot (n-a+1)) ]

    复杂度(O(sqrt{n}log{n}))
    计算(sum_{x=1}^{n}x^2)的公式是(frac{ncdot (n+1)cdot (2cdot n+1)}{6})

    //#pragma GCC optimize("O3")
    //#pragma comment(linker, "/STACK:1024000000,1024000000")
    #include<bits/stdc++.h>
    using namespace std;
    function<void(void)> ____ = [](){ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);};
    typedef long long int LL;
    const LL MOD = 998244353;
    LL qpow(LL a, LL b){
        LL ret = 1;
        while(b){
            if(b&1) ret = ret * a % MOD;
            a = a * a % MOD;
            b >>= 1;
        }
        return ret;
    }
    LL inv(LL x){ return qpow(x,MOD-2); }
    LL n;
    int main(){
        ____();
        cin >> n;
        int sqt = (int)sqrt(n);
        LL ret = 0;
        for(int a = 2; a <= sqt; a++){
            LL pre = a;
            int add = 0;
            while(true){
                add++;
                LL now = min(n,pre*a-1);
                ret = (ret + (now-pre+1) * add * a) % MOD;
                if(now==n) break;
                pre *= a;
            }
        }
        LL x = sqt + 1, m = n % MOD;
        ret = (ret + (m+1) % MOD * (x+m) % MOD * (m-x+1) % MOD * inv(2)) % MOD;
        ret = (ret - m * (m+1) % MOD * (2*m+1) % MOD * inv(6) % MOD + (x-1) * x % MOD * (2*x-1) % MOD * inv(6)) % MOD;
        if(ret < 0) ret += MOD;
        cout << ret << endl;
        return 0;
    }
    

    (G. Pot!!)
    (10)以内的质数只有(2,3,5,7),线段树维护区间内四个质数出现次数的最大值即可
    更新的时候区间内把(x)分解质因子之后区间更新

    //#pragma GCC optimize("O3")
    //#pragma comment(linker, "/STACK:1024000000,1024000000")
    #include<bits/stdc++.h>
    using namespace std;
    function<void(void)> ____ = [](){ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);};
    const int MAXN = 1e5+7;
    struct SegmentTree{
        int maxx[MAXN<<2][4],lazy[MAXN<<2][4];
        int l[MAXN<<2],r[MAXN<<2];
        #define ls(rt) rt << 1
        #define rs(rrt) rt << 1 | 1
        void pushup(int rt){
            for(int i = 0; i < 4; i++) maxx[rt][i] = max(maxx[ls(rt)][i],maxx[rs(rt)][i]);
        }
        void pushdown(int rt){
            for(int i = 0; i < 4; i++){
                if(!lazy[rt][i]) continue;
                maxx[ls(rt)][i] += lazy[rt][i]; lazy[ls(rt)][i] += lazy[rt][i];
                maxx[rs(rt)][i] += lazy[rt][i]; lazy[rs(rt)][i] += lazy[rt][i];
                lazy[rt][i] = 0;
            }
        }
        void build(int L, int R, int rt = 1){
            l[rt] = L, r[rt] = R;
            if(L+1==R) return;
            int mid = (L+R) >> 1;
            build(L,mid,ls(rt)); build(mid,R,rs(rt));
        }
        void update(int L, int R, int tg, int rt = 1){
            if(L>=r[rt] or l[rt]>=R) return;
            if(L<=l[rt] and r[rt]<=R){
                maxx[rt][tg]++;
                lazy[rt][tg]++;
                return;
            }
            pushdown(rt);
            update(L,R,tg,ls(rt)); update(L,R,tg,rs(rt));
            pushup(rt);
        }
        int query(int L, int R, int tg, int rt = 1){
            if(L>=r[rt] or l[rt]>=R) return 0;
            if(L<=l[rt] and r[rt]<=R) return maxx[rt][tg];
            pushdown(rt);
            return max(query(L,R,tg,ls(rt)),query(L,R,tg,rs(rt)));
        }
    }ST;
    int n,m;
    int main(){
        scanf("%d %d",&n,&m);
        ST.build(1,n+1);
        char op[20];
        for(int i = 1; i <= m; i++){
            scanf("%s",op);
            if(op[1]=='A'){
                int l, r, ret = 0; scanf("%d %d",&l,&r);
                r++;
                for(int k = 0; k < 4; k++) ret = max(ret,ST.query(l,r,k));
                printf("ANSWER %d
    ",ret);
            }
            else{
                int l, r, x; scanf("%d %d %d",&l,&r,&x);
                r++;
                while(x-1 and x%2==0) x/=2, ST.update(l,r,0);
                while(x-1 and x%3==0) x/=3, ST.update(l,r,1);
                while(x-1 and x%5==0) x/=5, ST.update(l,r,2);
                while(x-1 and x%7==0) x/=7, ST.update(l,r,3);
            }
        }
        return 0;
    }
    

    (H. Delivery Route)
    BZOJ2200
    Dijkstra不能跑负权图 所以可以先缩点,缩点完之后就是一个DAG,其中可以对每个连通块跑Dijkstra

    //#pragma GCC optimize("O3")
    //#pragma comment(linker, "/STACK:1024000000,1024000000")
    #include<bits/stdc++.h>
    using namespace std;
    function<void(void)> ____ = [](){ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);};
    const int MAXN = 2e5+7;
    const int INF = 0x3f3f3f3f;
    int n,x,y,s,sccid[MAXN],sid,deg[MAXN],dist[MAXN];
    bool vis[MAXN];
    vector<int> scc[MAXN];
    int Stk[MAXN], tp;
    bool instk[MAXN];
    int top(){ return Stk[tp]; }
    void pop(){ instk[Stk[tp--]] = false; }
    void push(int x){ instk[Stk[++tp]=x] = true; }
    bool check(int x){ return instk[x]; }
    struct Graph{
        int to[MAXN<<2],nxt[MAXN<<2],w[MAXN<<2],head[MAXN],tot;
        Graph(){}
        void ADDEDGE(int u, int v, int x){
            tot++;
            to[tot] = v; nxt[tot] = head[u]; w[tot] = x;
            head[u] = tot;
        }
    }G;
    void gao(int u, int id){
        sccid[u] = id;
        scc[id].push_back(u);
        for(int i = G.head[u]; i; i = G.nxt[i]) if(!sccid[G.to[i]]) gao(G.to[i],id);
    }
    void dfs(int u){
        vis[u] = true;
        for(int i = G.head[u]; i; i = G.nxt[i]) if(!vis[G.to[i]]) dfs(G.to[i]);
    }
    void rebuild(){
        for(int u = 1; u <= n; u++){
            if(!vis[u]) continue;
            for(int i = G.head[u]; i; i = G.nxt[i]){
                int v = G.to[i];
                if(!vis[v] or sccid[u]==sccid[v]) continue;
                deg[sccid[v]]++;
            }
        }
    }
    queue<int> que;
    priority_queue<pair<int,int>,vector<pair<int,int>>,greater<pair<int,int>>> pq;
    void Dijkstra(int ss){
        for(int v : scc[ss]) if(dist[v]!=INF) pq.push(make_pair(dist[v],v));
        while(!pq.empty()){ 
            auto p = pq.top();
            pq.pop();
            int u = p.second;
            if(dist[u]!=p.first) continue;
            for(int i = G.head[u]; i; i = G.nxt[i]){
                int v = G.to[i], w = G.w[i];
                if(!vis[v]) continue;
                if(sccid[v]!=sccid[u]) if(!--deg[sccid[v]]) que.push(sccid[v]);
                if(dist[v]>dist[u]+w){
                    dist[v] = dist[u] + w;
                    if(sccid[v]==sccid[u]) pq.push(make_pair(dist[v],v));
                }
            }
        }
    }
    void solve(){
        memset(dist,0x3f,sizeof(dist));
        dist[s] = 0;
        que.push(sccid[s]);
        while(!que.empty()){
            int ss = que.front();
            que.pop();
            Dijkstra(ss);
        }
        for(int i = 1; i <= n; i++){
            if(dist[i]==INF) puts("NO PATH");
            else printf("%d
    ",dist[i]);
        }
    }
    int main(){
        scanf("%d %d %d %d",&n,&x,&y,&s);
        for(int i = 1; i <= x; i++){
            int u, v, w; scanf("%d %d %d",&u,&v,&w);
            G.ADDEDGE(u,v,w); G.ADDEDGE(v,u,w);
        }
        for(int i = 1; i <= n; i++) if(!sccid[i]) gao(i,++sid);
        for(int i = 1; i <= y; i++){
            int u, v, w; scanf("%d %d %d",&u,&v,&w);
            G.ADDEDGE(u,v,w);
        }
        dfs(s);
        rebuild();
        solve();
        return 0;
    }
    

    (I. Base62)
    大数的进制转换,用不想写c++,那就用直接Java

    import java.io.*;
    import java.util.*;
    import java.math.*;
    public class Main{
        private static Scanner cin = new Scanner(new BufferedInputStream(System.in));
        private static PrintWriter cout = new PrintWriter(System.out,true);
        private static InputStream inputstream = System.in;
        public static void main(String[] args){
            Task solver = new Task();
            int TaskCase = 1;
            while(TaskCase--!=0){
                solver.solve();cout.flush();
            }
        }
        private static class Task{
            HashMap<Character,Integer> map1 = new HashMap<>();
            HashMap<Integer,Character> map2 = new HashMap<>();
            public void solve(){
                for(int i = 0; i <= 9; i++){
                    map1.put((char)(i+(int)('0')),i);
                    map2.put(i,(char)(i+(int)('0')));
                }
                for(int i = (int)('A'); i <= (int)('Z'); i++){
                    map1.put((char)(i),i-(int)('A')+10);
                    map2.put(i-(int)('A')+10,(char)(i));
                }
                for(int i = (int)('a'); i <= (int)('z'); i++){
                    map1.put((char)(i),i-(int)('a')+36);
                    map2.put(i-(int)('a')+36,(char)(i));
                }
                int base1 = cin.nextInt(), base2 = cin.nextInt();
                String str1 = cin.next();
                BigInteger bs1 = BigInteger.valueOf(base1);
                BigInteger bs2 = BigInteger.valueOf(base2);
                BigInteger base10 = BigInteger.ZERO;
                for(int i = 0; i < str1.length(); i++){
                    base10 = base10.multiply(bs1).add(BigInteger.valueOf(map1.get(str1.charAt(i))));
                }
                ArrayList<Integer> arr = new ArrayList<>();
                if(base10.equals(BigInteger.ZERO)) arr.add(0);
                while(!(base10.equals(BigInteger.ZERO))){
                    arr.add(base10.mod(bs2).intValue());
                    base10 = base10.divide(bs2);
                }
                for(int i = arr.size() - 1; i >= 0; i--) cout.write(map2.get(arr.get(i)));
            }
        }
    }
    

    (J. Toad’s Travel)

    (K. Largest Common Submatrix)
    由于(AB)两个矩阵中每个数都只出现一次,所以我们新建一个矩阵(C),矩阵里存放(A)中每个位置(x,y)对应的数在B矩阵中的位置和在(A)矩 阵中的位置的差值,现在问题转化为找一个最大的子矩阵(Mat)使得这个矩阵中的所有值相同,单调栈做就好了

    //#pragma GCC optimize("O3")
    //#pragma comment(linker, "/STACK:1024000000,1024000000")
    #include<bits/stdc++.h>
    using namespace std;
    function<void(void)> ____ = [](){ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);};
    const int MAXN = 1111;
    int n,m,A[MAXN][MAXN],B[MAXN][MAXN],f[MAXN][MAXN],l[MAXN],r[MAXN];
    pair<int,int> pos[MAXN*MAXN],mat[MAXN][MAXN];
    pair<int,int> operator - (const pair<int,int> &lhs, const pair<int,int> &rhs){
        return make_pair(lhs.first-rhs.first,lhs.second-rhs.second);
    }
    int main(){
        scanf("%d %d",&n,&m);
        for(int i = 1; i <= n; i++) for(int j = 1; j <= m; j++) scanf("%d",&A[i][j]);
        for(int i = 1; i <= n; i++) for(int j = 1; j <= m; j++) scanf("%d",&B[i][j]), pos[B[i][j]] = make_pair(i,j);
        for(int i = 1; i <= n; i++) for(int j = 1; j <= m; j++) mat[i][j] = make_pair(i,j) - pos[A[i][j]];
        for(int i = 1; i <= n; i++) for(int j = m; j >= 1; j--){
            f[i][j] = 1; if(j==m) continue;
            if(mat[i][j]==mat[i][j+1]) f[i][j] += f[i][j+1];
        }
        int ret = 0;
        for(int i = 1; i <= m; i++){
            stack<int> stk;
            memset(l,0,sizeof(l)); memset(r,0,sizeof(r));
            for(int j = 1; j <= n; j++){
                if(!stk.empty()){
                    if(mat[j][i]!=mat[j-1][i]){
                        while(!stk.empty()){
                            r[stk.top()] = j - 1;
                            stk.pop();
                        }
                    }
                }
                while(!stk.empty() and f[j][i]<f[stk.top()][i]){
                    l[j] = l[stk.top()];
                    r[stk.top()] = j - 1;
                    stk.pop();
                }
                if(!l[j]) l[j] = j;
                stk.push(j);
            }
            while(!stk.empty()){
                r[stk.top()] = n;
                stk.pop();
            }
            for(int j = 1; j <= n; j++) ret = max(ret,(r[j]-l[j]+1)*f[j][i]);
        }
        cout << ret << endl;
        return 0;
    }
    

    (L. Xian Xiang)

    (M. Crazy Cake)

    (N. Fibonacci Sequence)
    输出(1,1,2,3,5)
    python写一行就完了

    print(1,1,2,3,5)
    
  • 相关阅读:
    python列表解析和正同表达式
    python实现屏幕截图
    pngCanvas 是一个使用纯Python代码的生成png图像的工具
    windows 7 提示升级到windows 10补丁
    openerp所用QWEB2的调试笔记
    修改 Ubuntu 13.04 LAMP 服务器端口号
    DEB方式在UBUNTU安装ODOO 8.0
    在openerp撰写消息中增加图片
    ubuntu挂载3T新硬盘并更换home分区
    MPEG-4 压缩编码标准
  • 原文地址:https://www.cnblogs.com/kikokiko/p/12761334.html
Copyright © 2011-2022 走看看