zoukankan      html  css  js  c++  java
  • 牛客OI测试赛3

    题目链接:https://www.nowcoder.com/acm/contest/189#question

    A.数字权重

    $\sum{i=2}^na_i-a{i-1} =a_n-a_1$,因而方案数与$n$大小以及第一个数字和最后一个数字有关

    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    #include<stack>
    #include<vector>
    using namespace std;
    typedef long long ll;
    const int maxn=36;
    vector<int> g[maxn];
    ll dp[maxn][maxn];
    const ll mod=1e9+7;
    ll powmod(ll a,ll n){
        if(n==0)   return 1;
        if(n==1)   return a%mod;
        ll ans=powmod(a,n/2);
        ans=ans*ans%mod;
        if(n&1) return  ans*a%mod;
        return ans;
    }
    int main(){
        ll n,k;
        cin>>n>>k;
        if(k>=10||k<=-10){
            cout<<0<<endl;
            return 0;
        }
        ll ans=0;
        if(k>=0)
            cout<<(9-k)*powmod((ll)10,n-2)%mod;
        else cout<<(10+k)*powmod((ll)10,n-2)%mod;
    }

    B.毒瘤XOR

    首先,考虑到结果的每一位之间互相不影响,因而可以对每一位分别计算,对于区间[L,R]中的每一位,如果0的个数大于1的个数,则该位取1,否则该位取0

    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    #include<stack>
    #include<vector>
    using namespace std;
    typedef unsigned long long ll;
    const int maxn=200005;
    int p[31];
    int a[33][maxn];
    int main(){
        p[0]=1;
        for(int i=1;i<=30;i++)
            p[i]=p[i-1]*2;
        int n;
        scanf("%d",&n);
        for(int i=1;i<=n;i++){
            int z;
            scanf("%d",&z);
            for(int j=0;j<=30;j++){
                if((z>>j)&1)
                    a[j][i]=1;
            }
        }
        for(int j=0;j<=30;j++)
            for(int i=1;i<=n;i++)
                a[j][i]+=a[j][i-1];
        int q;
        scanf("%d",&q);
        for(int i=1;i<=q;i++){
            int l,r;
            scanf("%d%d",&l,&r);
            int z=0;
            for(int i=0;i<=30;i++){
                if(a[i][r]-a[i][l-1]<(r-l+2)/2)
                    z+=p[i];
            }
            printf("%d\n",z);
        }
    }

    C.硬币游戏

    简单博弈论:对于每一个位置,分三种情况:先手能拿,后手能拿,二者都可以拿。分别计算这三种情况的个数分别为s1,s2,sum 必胜策略肯定是二者都取sum中的硬币,易知其必胜情况

    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    #include<stack>
    #include<vector>
    using namespace std;
    typedef unsigned long long ll;
    const int maxn=2000005;
    char s[maxn],t[maxn];
    int main(){
        int n;
        scanf("%d",&n);
        scanf("%s",s);
        scanf("%s",t);
        int s1=0,s2=0,sum=0;
        for(int i=0;i<2*n;i++){
            if(s[i]=='U'&&t[i]=='U')
                sum++;
            else if(s[i]=='U')
                s1++;
            else if(t[i]=='U')
                s2++;
        }
        if(s1>s2||(s1==s2&&sum%2==1))
            cout<<"clccle trl!"<<endl;
        else if((s1==s2&&sum%2==0)||(s2-s1==1&&sum%2==1))
            cout<<"orz sarlendy!"<<endl;
        else cout<<"sarlendy tql!"<<endl;
    }

    D.粉樱花之恋

    斐波拉契求和,答案即为$sum[k+1]$,矩阵快速幂即可

    $fib[i+2]=2fib[i]+fib[i-1]=fib[i]+2fib[i-1]+fib[i-2]=fib[i]+fib[i-1]+2fib[i-2]+fib[i-3]=...=fib[i]+...+2f[2]+f[1]=sum[i]+1$

    故$sum[i]=f[i+2]-1$  sum[i]=f[i+2]-1

    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    #include<stack>
    #include<vector>
    using namespace std;
    typedef unsigned long long ll;
    const ll mod=998244353;
    struct Matrix{
        ll m[2][2];
    };
    Matrix mul(Matrix a,Matrix b){
        Matrix m;
        for(int i=0;i<2;i++)
        for(int j=0;j<2;j++){
            ll sum=0;
            for(int k=0;k<2;k++)
                sum=(sum+a.m[i][k]*b.m[k][j]%mod)%mod;
            m.m[i][j]=sum;
        }
        return m;
    }
    Matrix matrix_quick_powmod(Matrix a,ll n){
        Matrix m,p;
        m.m[0][0]=m.m[0][1]=m.m[1][0]=1ll;
        m.m[1][1]=0;
        if(n==0){
            m.m[0][0]=m.m[1][1]=1ll;
            m.m[0][1]=m.m[1][0]=0;
            return m;
        }
        if(n==1) return m;
        else p=matrix_quick_powmod(m,n/2);
        p=mul(p,p);
        if(n&1)
            p=mul(p,m);
        return p;
    }
    
    Matrix a,b;
    int main(){
        ll n;
        cin>>n;
        for(int i=0;i<2;i++)
            for(int j=0;j<2;j++)
                if(i+j!=2)
                a.m[i][j]=b.m[i][j]=1ll;
        a=matrix_quick_powmod(a,n+2);
        cout<<(a.m[0][0]-1+mod)%mod<<endl;
    }

    E.符合条件的整数

    每7个数有一个数满足$i\%7=1$

    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    #include<stack>
    #include<vector>
    using namespace std;
    typedef long long ll;
    const int maxn=36;
    vector<int> g[maxn];
    ll dp[maxn][maxn];
    const ll mod=1e9+7;
    int main(){
        int a,b;
        ll m=1,n=1;
        cin>>a>>b;
        for(int i=1;i<=a;i++)
            m*=2;
        for(int i=1;i<=b;i++)
            n*=2;
        ll i,ans=0;
        for(i=n-1;i>=m;i--){
            if(i%7==m%7){
                if(i%7==1)
                    ans++;
                break;
            }
            if(i%7==1)
                ans++;
        }
        cout<<ans+max((ll)0,i-m)/7<<endl;
    }

    F.可爱即正义

    写了个KMP其实暴力即可,因为匹配串不特殊,如果未出现,则不能随意调换,否则换了之后可能匹配了,先将第一个字符和第二个字符,判断是否匹配,如果匹配就换第一个和第三个字符,如果只出现一次,则调换匹配串第一个字符和第二个字符,如果出现两次,则调换第一次出现的第一个字符和第二次出现的第二个字符

    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    #include<stack>
    #include<vector>
    using namespace std;
    typedef unsigned long long ll;
    const int maxn=1000005;
    vector<int> ans;
    void cal_next(char *str,int *next,int len){
        next[0]=-1;
        int k=-1;
        for(int q=1;q<=len-1;q++){
            while(k>-1&&str[k+1]!=str[q]){
                k=next[k];
            }
            if(str[k+1]==str[q])
                k++;
            next[q]=k;
        }
    }
    bool KMP(char *str,int slen,char *ptr,int plen){
        int *next=new int[plen];
        cal_next(ptr,next,plen);
        int k=-1;
        bool f=0;
        for(int i=0;i<slen;i++){
            while(k>-1&&ptr[k+1]!=str[i])
                k=next[k];
            if(ptr[k+1]==str[i])
                k++;
            if(k==plen-1){
                f=1;
                ans.push_back(i-plen+1);
                k=i-plen+2;
            }
        }
        return f;
    }
    char s[maxn],t[maxn]={"suqingnianloveskirito"};
    int main(){
        scanf("%s",s);
        int slen=strlen(s);
        int tlen=strlen(t);
        //cout<<t<<-1<<endl;
        KMP(s,slen,t,tlen);
       // cout<<-1<<endl;
        if(slen==1){
            cout<<"No"<<endl;
            return 0;
        }
        if(slen<=11){
            cout<<"Yes"<<endl;
            cout<<1<<" "<<2<<endl;
            return 0;
        }
    
        if(ans.size()==0){
            swap(s[0],s[1]);
            if(KMP(s,slen,t,tlen))
            cout<<"Yes"<<endl<<1<<" "<<3<<endl;
            else cout<<"Yes"<<endl<<1<<" "<<2<<endl;
        }
        else if(ans.size()==1){
            cout<<"Yes"<<endl<<ans[0]+1<<" "<<ans[0]+2<<endl;
        }
        else if(ans.size()==2){
            cout<<"Yes"<<endl<<ans[0]+1<<" "<<ans[1]+2<<endl;
        }
        else{
            cout<<"No"<<endl;
        }
    }
    

      

  • 相关阅读:
    vim 常用命令
    centos 安装mysql
    centos部署ftp
    centos 6.8部署nginx
    ndk学习16: unix domain socket
    ndk学习14: 进程
    ndk学习13: proc
    ndk学习11: linux内存管理
    ndk学习10: linux文件系统
    ndk学习9: 动态使用共享库
  • 原文地址:https://www.cnblogs.com/dlutjwh/p/10986818.html
Copyright © 2011-2022 走看看