• 2019牛客多校第十场


    B Coffee Chicken

    题意

    定义一个字符串的斐波那契数列,求从第k位开始的后面十个字符。

    分析

    • 把第n项求出来是不可能的。
    • 斐波那契数列的增长是很快的,而且由于题目保证(k<=min(|S(n)|,10^{12})),且只输出十个字符,因此其实只有前几十项是有用的。
    • 把前面几十项的长度和字符串预处理出来,然后分治输出即可。

    代码

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    int T,n;
    ll k,l[65];
    string s[25];
    void solve(int n,ll k,ll num){
        if(n<=20){
            for(int i=k-1,j=0;i<l[n] && j<num;i++,j++){
                printf("%c",s[n][i]);
            }
            return;
        }
        if(k+num<=l[n-2]){
            solve(n-2,k,num);
        }else if(k>l[n-2]){
            solve(n-1,k-l[n-2],num);
        }else{
            solve(n-2,k,l[n-2]-k+1);
            solve(n-1,1,num-(l[n-2]-k+1));
        }
    }
    int main(){
    //    freopen("in.txt","r",stdin);
        l[1]=6;
        l[2]=7;
        s[1]="COFFEE";
        s[2]="CHICKEN";
        for(int i=3;i<=60;i++){
            l[i]=l[i-2]+l[i-1];
        }
        for(int i=3;i<=20;i++){
            s[i]=s[i-2]+s[i-1];
        }
        scanf("%d",&T);
        while(T--){
            scanf("%d%lld",&n,&k);
            n=min(n,60);
            solve(n,k,10);
            printf("
    ");
        }
        return 0;
    }
    

    D Han Xin and His Troops

    题意

    拓展中国剩余定理。

    分析

    不会数学,负责帮队友写了个Java大数版本。

    代码

    import java.io.*;
    import java.math.BigInteger;
    import java.util.Scanner;
     
    public class Main {
     
        static BigInteger[] b=new BigInteger[150];
        static BigInteger[] a=new BigInteger[150];
        static int n;
        static BigInteger m;
        public static BigInteger exgcd(BigInteger a,BigInteger b,BigInteger[] x,BigInteger[] y){
            if(a.compareTo(BigInteger.ZERO)==0 && b.compareTo(BigInteger.ZERO)==0){
                return new BigInteger("-1");
            }
            if(b.compareTo(BigInteger.ZERO)==0){
                x[0]= BigInteger.ONE;
                y[0]=BigInteger.ZERO;
                return a;
            }
            BigInteger d=exgcd(b,a.mod(b),y,x);
            y[0]=y[0].subtract(a.divide(b).multiply(x[0]));
            return d;
        }
        static BigInteger excrt(){
            BigInteger[] x=new BigInteger[2];
            BigInteger[] y=new BigInteger[2];
            BigInteger M=b[1];
            BigInteger ans=a[1];
            for(int i=2;i<=n;i++){
                BigInteger ai=M,bi=b[i],ci=(a[i].subtract(ans.mod(bi)).add(bi)).mod(bi);
                BigInteger gcd=exgcd(ai,bi,x,y);
                BigInteger bg=bi.divide(gcd);
                if(ci.mod(gcd).compareTo(BigInteger.ZERO)!=0){
                    return new BigInteger("-1");
                }
                x[0]=x[0].multiply(ci.divide(gcd)).mod(bg);
                ans=ans.add(x[0].multiply(M));
                M=M.multiply(bg);
                ans=(ans.mod(M).add(M)).mod(M);
            }
            return (ans.mod(M).add(M)).mod(M);
        }
        public static void main(String[] args) {
            Scanner cin=new Scanner(System.in);
            n=cin.nextInt();
            m=cin.nextBigInteger();
            for(int i=1;i<=n;i++){
                b[i]=cin.nextBigInteger();
                a[i]=cin.nextBigInteger();
            }
            BigInteger ans=excrt();
            if(ans.compareTo(BigInteger.valueOf(-1))==0){
                System.out.println("he was definitely lying");
            }else if(ans.compareTo(m)>0){
                System.out.println("he was probably lying");
            }else{
                System.out.println(ans);
            }
        }
    }
    
    

    F Popping Balloons

    题意

    在一个二维平面有一些气球,横着打三枪竖着打三枪,要使打到的气球数最多。

    分析

    • 首先肯定是行列肯定是枚举一个,维护另一个,这里我们考虑枚举列,然后维护行打三枪的最大值。
    • 考虑到列的影响,行的最值需要用线段树来维护,我们定义行(i)的值(v[i])表示打了(i,i+r,i+2*r)三枪的最大值,那么枚举打了第(j,j+r,j+2*r)列时,这些列上对应的行的气球就被列的打掉,所以对行的贡献就没了
    • 因此对于枚举的列的每个行(k),将(k,k-r,k-2*r)(v[k])贡献减去即可。

    代码

    #include <bits/stdc++.h>
    using namespace std;
    #define ls i<<1
    #define rs i<<1|1
    #define mid (l+r)/2
    const int N=1e5+50;
    const int MAX=1e5+1;
    int n,R,x,y;
    vector<int> g[N];
    int h[N],s[N];
    int mx[N*4];
    void pushup(int i){
        mx[i]=max(mx[ls],mx[rs]);
    }
    void build(int i,int l,int r){
        if(l==r){
            mx[i]=s[l];
            if(l+R<=MAX){
                mx[i]+=s[l+R];
            }
            if(l+2*R<=MAX){
                mx[i]+=s[l+2*R];
            }
            return;
        }
        build(ls,l,mid);
        build(rs,mid+1,r);
        pushup(i);
    }
    void update(int i,int l,int r,int p,int v){
        if(l==r && l==p){
            mx[i]+=v;
            return;
        }
        if(p<=mid){
            update(ls,l,mid,p,v);
        }else{
            update(rs,mid+1,r,p,v);
        }
        pushup(i);
    }
    int main(){
    //    freopen("in.txt","r",stdin);
        scanf("%d%d",&n,&R);
        for(int i=0;i<n;i++){
            scanf("%d%d",&x,&y);
            x++;
            y++;
            h[x]++;
            s[y]++;
            g[x].push_back(y);
        }
        int ans=0;
        build(1,1,MAX);
        for(int i=1;i<=MAX;i++){
            int tmp=h[i];
            int siz=g[i].size();
            for(int j=0;j<siz;j++){
                int v=g[i][j];
                update(1,1,MAX,v,-1);
                if(v-R>=1){
                    update(1,1,MAX,v-R,-1);
                }
                if(v-2*R>=1){
                    update(1,1,MAX,v-2*R,-1);
                }
            }
            if(i+R<=MAX){
                tmp+=h[i+R];
                siz=g[i+R].size();
                for(int j=0;j<siz;j++){
                    int v=g[i+R][j];
                    update(1,1,MAX,v,-1);
                    if(v-R>=1){
                        update(1,1,MAX,v-R,-1);
                    }
                    if(v-2*R>=1){
                        update(1,1,MAX,v-2*R,-1);
                    }
                }
            }
            if(i+2*R<=MAX){
                tmp+=h[i+2*R];
                siz=g[i+2*R].size();
                for(int j=0;j<siz;j++){
                    int v=g[i+2*R][j];
                    update(1,1,MAX,v,-1);
                    if(v-R>=1){
                        update(1,1,MAX,v-R,-1);
                    }
                    if(v-2*R>=1){
                        update(1,1,MAX,v-2*R,-1);
                    }
                }
            }
            ans=max(ans,tmp+mx[1]);
            siz=g[i].size();
            for(int j=0;j<siz;j++){
                int v=g[i][j];
                update(1,1,MAX,v,1);
                if(v-R>=1){
                    update(1,1,MAX,v-R,1);
                }
                if(v-2*R>=1){
                    update(1,1,MAX,v-2*R,1);
                }
            }
            if(i+R<=MAX){
                siz=g[i+R].size();
                for(int j=0;j<siz;j++){
                    int v=g[i+R][j];
                    update(1,1,MAX,v,1);
                    if(v-R>=1){
                        update(1,1,MAX,v-R,1);
                    }
                    if(v-2*R>=1){
                        update(1,1,MAX,v-2*R,1);
                    }
                }
            }
            if(i+2*R<=MAX){
                siz=g[i+2*R].size();
                for(int j=0;j<siz;j++){
                    int v=g[i+2*R][j];
                    update(1,1,MAX,v,1);
                    if(v-R>=1){
                        update(1,1,MAX,v-R,1);
                    }
                    if(v-2*R>=1){
                        update(1,1,MAX,v-2*R,1);
                    }
                }
            }
        }
        printf("%d
    ",ans);
        return 0;
    }
    

    H Stammering Chemists

    题意

    给一个6个点的树,判断属于题目中的哪一种。

    分析

    根据度数判断即可。

    代码

    #include <bits/stdc++.h>
    using namespace std;
    int T,u,v,ind[10],cnt[10];
    vector<int> g[10];
    int main(){
    //    freopen("in.txt","r",stdin);
        scanf("%d",&T);
        while(T--){
            memset(ind,0,sizeof(ind));
            memset(cnt,0,sizeof(cnt));
            for(int i=1;i<=6;i++){
                g[i].clear();
            }
            for(int i=0;i<5;i++){
                scanf("%d%d",&u,&v);
                ind[u]++;
                ind[v]++;
                g[u].push_back(v);
                g[v].push_back(u);
            }
            for(int i=1;i<=6;i++){
                cnt[ind[i]]++;
            }
            if(cnt[2]==4 && cnt[1]==2){
                printf("n-hexane
    ");
            }else if(cnt[4]>0){
                printf("2,2-dimethylbutane
    ");
            }else if(cnt[3]==2 && cnt[1]==4){
                printf("2,3-dimethylbutane
    ");
            }else{
                int rt=0;
                for(int i=1;i<=6;i++){
                    if(ind[i]==3){
                        rt=i;
                        break;
                    }
                }
                int a[3]={0};
                for(auto v:g[rt]){
                    a[ind[v]]++;
                }
                if(a[1]==1 && a[2]==2){
                    printf("3-methylpentane
    ");
                }else{
                    printf("2-methylpentane
    ");
                }
            }
        }
        return 0;
    }
    
  • 相关阅读:
    java源码之HashMap和HashTable的异同
    java源码之HashMap
    进制转换
    java基本数据类型及其包装类
    java实例化对象的五种方法
    20 栈的压入、弹出序列
    19 包含min函数的栈
    18 顺时针打印矩阵(记忆,常忘记)
    16 树的子结构(这题多复习)
    15合并两个排序的链表
  • 原文地址:https://www.cnblogs.com/zxcoder/p/11378988.html
Copyright © 2020-2023  润新知