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;
        }
    }
    

      

  • 相关阅读:
    微信 token ticket jsapi_ticket access_token 获取 getAccessToken get_jsapi_ticket方法
    PHP 日志 记录 函数 支持 数组 对象 新浪 sae 环境 去掉 空格 换行 格式化 输出 数组转字符串
    原生 原始 PHP连接MySQL 代码 参考mysqli pdo
    PHP 数字金额转换成中文大写金额的函数 数字转中文
    使用PHPMailer发送带附件并支持HTML内容的邮件
    设置输出编码格式 header 重定向 执行时间 set_time_limit 错误 报告 级别 error_reporting
    html5 bootstrap pannel table 协议 公告 声明 文书 模板
    指向指针的指针
    二级指针
    c语言:当指针成为参数后
  • 原文地址:https://www.cnblogs.com/dlutjwh/p/10986818.html
Copyright © 2011-2022 走看看