zoukankan      html  css  js  c++  java
  • bzoj 3328 : PYXFIB

    Discription

    Input

    第一行一个正整数,表示数据组数据 ,接下来T行
    每行三个正整数N,K,P

    Output

    T行,每行输出一个整数,表示结果

    Sample Input
    1
    1 2 3

    Sample Output

    1

    Hint

         上个周学的一个 dark技巧: 利用单位根来 求一个多项式某个数倍数次数的项的系数和。

        首先设 w[k] 为 复数域下的k次单位根,那么它满足的一个性质是: 当且仅当 k|i 的时候 ,w[k]^i = 1;其他时候都不为1。

        这个有什么用处呢???

        假设我们要求 杨辉三角的第n行的 是3的倍数的列的和的时候, 我们显然可以列出式子:ANS = ∑ [k|i] * C(n,i).

        然后我们把 w[0]~w[k-1] 分别带进 (1+x)^n 这个多项式里,展开之后求和,显然 x^i前的系数是 C(n,i) ,并且  对于 是k的倍数的i ,w[0]^i + w[1]^i +....+w[k-1]^i = k;

    而对于不是k倍数的i,我们用等比数列求一下和发现系数正好就是0。所以我们把这k个多项式的和再除以k就是要求的东西了。

        对于本题其实是一样的,只不过我们把数的多项式换成矩阵的多项式就好啦。而且因为 p mod k =1,所以直接找原根然后就可以直接求k次单位根啦。

    (无意间达成了一个成就2333  )

    /*
        利用单位根的性质,可以求出多项式某个数倍数的次数项的系数和
    	(I + xA)^n = ∑C(n,i) * x^i * A^i ,其中A是斐波那契数列系数矩阵 
    */
    #include<bits/stdc++.h>
    #define ll long long
    using namespace std;
    int K,P,T,root,num,d[233],ans;
    inline int add(int x,int y){ x+=y; return x>=P?x-P:x;}
    inline int mul(int x,int y,const int ha){ return x*(ll)y%ha;}
    inline int ksm(int x,int y){ int an=1; for(;y;y>>=1,x=mul(x,x,P)) if(y&1) an=mul(an,x,P); return an;}
    struct node{
    	int a[2][2];
    	inline void clear(){ memset(a,0,sizeof(a));}
    	inline void BASE(){ clear(); a[0][0]=a[1][1]=1;}
    	node operator *(const int &u)const{
    		node r;
    		r.a[0][0]=mul(a[0][0],u,P);
    		r.a[0][1]=mul(a[0][1],u,P);
    		r.a[1][0]=mul(a[1][0],u,P);
    		r.a[1][1]=mul(a[1][1],u,P);
    		return r;
    	}
    	node operator +(const node &u)const{
    		node r;
    		r.a[0][0]=add(a[0][0],u.a[0][0]);
    		r.a[0][1]=add(a[0][1],u.a[0][1]);
    		r.a[1][0]=add(a[1][0],u.a[1][0]);
    		r.a[1][1]=add(a[1][1],u.a[1][1]);
    		return r;
    	}
    	node operator *(const node &u)const{
    		node r;
    		r.a[0][0]=add(mul(a[0][0],u.a[0][0],P),mul(a[0][1],u.a[1][0],P));
    		r.a[0][1]=add(mul(a[0][1],u.a[1][1],P),mul(a[0][0],u.a[0][1],P));
    		r.a[1][0]=add(mul(a[1][0],u.a[0][0],P),mul(a[1][1],u.a[1][0],P));
    		r.a[1][1]=add(mul(a[1][1],u.a[1][1],P),mul(a[1][0],u.a[0][1],P));
    		return r;		
    	}
    }X,ANS;
    
    inline void GD(){
    	int Q=P-1; num=0;
    	for(int i=2;i*(ll)i<=Q;i++) if(!(Q%i)){
    		d[++num]=i;
    		while(!(Q%i)) Q/=i;
    		if(Q==1) break;
    	}
    	if(Q!=1) d[++num]=Q; 
    	for(int i=1;i<=num;i++) d[i]=(P-1)/d[i];
    }
    
    inline void findroot(){
        GD();
        for(int i=2;i;i++){
        	bool flag=1;
        	for(int j=1;j<=num;j++) if(ksm(i,d[j])==1){ flag=0; break;}
        	
    		if(flag){ root=i; break;}
    	}
    }
    
    inline void calc(ll C){
    	for(int i=0,omega=ksm(root,(P-1)/K),now=1;i<K;i++,now=mul(now,omega,P)){
    	    X.a[0][1]=X.a[1][1]=X.a[1][0]=1,X.a[0][0]=0;
    	    X=X*now,X.a[0][0]=add(X.a[0][0],1),X.a[1][1]=add(X.a[1][1],1);
    	    
    	    ll O=C; ANS.BASE();
    	    for(;O;O>>=1,X=X*X) if(O&1) ANS=ANS*X;
    	    
    	    ans=add(ans,add(ANS.a[0][0],ANS.a[1][0]));
    	}
    	ans=mul(ans,ksm(K,P-2),P);
    }
    
    inline void solve(){
    	ll N; ans=0;
    	scanf("%lld%d%d",&N,&K,&P);
    	findroot();
    	calc(N);
    	printf("%d
    ",ans);
    }
    
    int main(){
    	scanf("%d",&T);
    	while(T--) solve();
    	return 0;
    }
    

      

  • 相关阅读:
    Django——model(建表,增删改查,外键,多对多)
    Django——model中的参数
    Django——路由系统,视图(接收文件等)
    Django——创建Django工程,app,模板语言
    前端——jQuery
    前端——DOM(添加标签,属性操作,各个事件,操作标签)
    前端——CSS
    Velocity模版自定义标签
    Velocity模版自定义标签
    Velocity模版自定义标签
  • 原文地址:https://www.cnblogs.com/JYYHH/p/8881386.html
Copyright © 2011-2022 走看看