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

  

 

posted @ 2021-12-04 16:01  dlutjwh  阅读(45)  评论(0编辑  收藏  举报