• vijos 2035 奇数偶数与绚丽多彩的数


    描述

    Q先生是一个热爱学习的男孩子。

    他认为一个 n 位的正整数 x 若能被称作是绚丽多彩的,一定要满足对于{1,3,5,7,9} 中任意一个奇数或者没有在 x 中出现,或者在 x 中出现了恰好奇数次;同时对于 {0,2,4,6,8} 中任意的偶数或者没有在 x 中出现,或者在x 中出现了偶数次。同时需要注意 x 是不能有前导零的。

    例如 141221242 就是一个九位的绚丽多彩的数。

    现在Q先生给定了正整数 n 与另外一个正整数 p,希望你统计出来一共有多少不超过 n 位的绚丽多彩的数,并输出模 p后的余数。

    格式

    输入格式

    输入有一行,包含两个由空格隔开的正整数,分别为 n 和 p

    输出格式

    输出一个正整数,表示不超过 n 位的绚丽多彩数的总数模 p 后的余数。

    样例1

    样例输入1

    7 1000000123

    样例输出1

    287975

    样例2

    样例输入2

    100 1000000123
    

    样例输出2

    123864868
    

    限制

    对于100%的数据,2<=n<=2^60,10^9<=p<=2*10^9。

        昨晚打的某个比赛的题。

        我们发现偶数出现偶数次和不出现都等价于出现的次数%2=0,奇数出现奇数次相当于出现次数%2=1,当然奇数还可能不出现。所以我们可以枚举哪些奇数是不出现的,然后剩下的奇数满足出现奇数次,偶数出现偶数次就行了。

        还可以发现我们没有必要知道每个奇数/偶数出现的次数的奇偶性,只需要知道有多少个 奇数/偶数 出现 奇数/偶数 次就行了。也就是状态压缩之后,我们只需要一个两位的五进制数就可以表示一个状态。

        而我们在外层也可以直接枚举有几个奇数出现过,然后再将这种情况下的方案总数乘上一个组合数就行了。

        但是这个题要求的数是<=n位的没有前导零的满足条件的数的个数,所以我们要求的最终转移方阵不是某个方阵A的n-1次方,而是A^0+A^1+....A^(n-1)。这个推一推式子就可以用类似矩阵快速幂的方法求出。

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cmath>
    #include<algorithm>
    #include<cstring>
    #define ll long long
    using namespace std;
    ll N,P,n,ans=0,C[10][10];
    
    inline ll add(ll x,ll y){
    	x+=y;
    	return x>=P?x-P:x;
    }
    
    struct node{
    	ll a[41][41];
    	
    	inline void clear(){
    		memset(a,0,sizeof(a));
    	}
    	
    	inline void init(){
    		clear();
    		for(int i=0;i<n;i++) a[i][i]=1;
    	} 
    	
    	node operator *(const node &u)const{
    		node r;
    		r.clear();
    		for(int k=0;k<n;k++)
    		    for(int i=0;i<n;i++)
    		        for(int j=0;j<n;j++) r.a[i][j]=add(r.a[i][j],a[i][k]*(ll)u.a[k][j]%P);
    		return r;
    	}
    	
    	node operator +(const node &u)const{
    		node r;
    		for(int i=0;i<n;i++)
    		    for(int j=0;j<n;j++) r.a[i][j]=add(a[i][j],u.a[i][j]);
    		return r;
    	}
    }base,ANS;
    
    inline node ksm(node x,ll y){
    	node r,q,BA=x; r.init(),q.init();
    	int i=60;
    	for(;i;i--) if((1ll<<i)&y) break;
    	r=x,i--;
    	for(;i>=0;i--)
    	    if((1ll<<i)&y){
    	    	node O=x*BA;
    	    	r=r*(q+O)+O;
    	    	x=x*O;
    		} 
    		else{
    			r=r*(q+x);
    			x=x*x;
    		}
    	
    	return r+q;
    }
    
    inline void solve(){
    	for(int i=0;i<=5;i++){
    		base.clear();
    		n=(i+1)*6;
    		for(int j=0,X,Y;j<n;j++){
    			X=j%6,Y=j/6;
    			if(X) base.a[j][j-1]=X;
    			if(X<5) base.a[j][j+1]=5-X;
    			if(Y) base.a[j][j-6]=Y;
    			if(Y<5) base.a[j][j+6]=i-Y;			
    		}
    		
    		ANS=ksm(base,N-1);
    		ans=add(ans,C[5][i]*(ll)((4*ANS.a[1][i*6]+i*ANS.a[6][i*6])%P)%P);
    	}
    	
    	printf("%lld
    ",ans);
    }
    
    int main(){
    	C[0][0]=1;
    	for(int i=1;i<=5;i++){
    		C[i][0]=1;
    		for(int j=1;j<=i;j++) C[i][j]=C[i-1][j-1]+C[i-1][j];
    	}
    	scanf("%lld%lld",&N,&P);
    	solve();
    	return 0;
    }
    

      

        

  • 相关阅读:
    Request的方法演示
    Request内置对象
    Servlet运行机制
    Servlet生命周期
    Servlet概念与配置
    http协议
    数据库连接池
    代码管理git托管到码云(github)开源中国
    事务
    类的执行先后顺序
  • 原文地址:https://www.cnblogs.com/JYYHH/p/8645367.html
Copyright © 2020-2023  润新知