zoukankan      html  css  js  c++  java
  • [题解]NOI2012 随机数据生成器

    题目描述

    (X_i=(aX_{i-1}+c)mod M)

    给出(X_0,a,c,M,G,n),求(X_n)%(G)

    分析

    我怎么会说自己一上来就打逆元然后直接GG呢

    先把式子化成(a^n*X_0)+一个等比数列(*C)

    随便一波发现可以用矩乘,然后直接矩乘杀进去(数学老师附体)

    或者可以递推,每一次都可以把等比数列拆成两半,复杂度是log的

    代码

    #include<bits/stdc++.h>
    #define rep(X,A,B) for(int X=A;X<=B;X++)
    #define tep(X,A,B) for(int X=A;X>=B;X--)
    #define LL long long
    using namespace std;
    
    LL MOD,ra,c,Xl,n,G;
    
    LL MSC(LL x,LL y){
    	LL res=0;
    	x%=MOD;y%=MOD;
    	while(y){
    		if(y&1)res=(res+x)%MOD;
    		x=(x+x)%MOD;
    		y/=2;
    	}
    	return res;
    }
    
    struct nn{
    	LL a[5][5];
    	
    	void INIT(){
    		a[1][1]=a[1][2]=a[2][1]=a[2][2]=0;
    	}
    };
    
    nn MUL(nn A,nn B){
    	nn X;
    	rep(i,1,2)rep(j,1,2){
    		X.a[i][j]=0;
    		rep(k,1,2)X.a[i][j]+=MSC(A.a[i][k],B.a[k][j]),X.a[i][j]%=MOD;
    	}
    	return X;
    }
    
    nn KSM(nn X,LL y){
    	nn res;
    	res.INIT();
    	res.a[1][1]=res.a[2][2]=1;
    	while(y){
    		if(y&1)res=MUL(res,X);
    		X=MUL(X,X);
    		y/=2;
    	}
    	return res;
    }
    
    void READ(){
    	scanf("%lld%lld%lld%lld%lld%lld",&MOD,&ra,&c,&Xl,&n,&G);
    }
    
    void SOLVE(){
    	nn A;
    	A.INIT();
    	A.a[1][1]=ra;A.a[2][1]=c;A.a[2][2]=1;A.a[1][2]=0;
    	A=KSM(A,n);
    	printf("%lld
    ",(MSC(Xl,A.a[1][1])+A.a[2][1])%MOD%G);
    }
    
    int main(){
    	READ();
    	SOLVE();
    	return 0;
    }
    
  • 相关阅读:
    LeetCode
    LeetCode
    LeetCode
    LeetCode
    LeetCode
    LeetCode
    LeetCode
    LeetCode
    LeetCode
    codevs 1501 二叉树最大宽度和高度x
  • 原文地址:https://www.cnblogs.com/SCL123/p/11760142.html
Copyright © 2011-2022 走看看