zoukankan      html  css  js  c++  java
  • BZOJ2875 [Noi2012]随机数生成器

    本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作。

    本文作者:ljh2000
    作者博客:http://www.cnblogs.com/ljh2000-jump/
    转载请注明出处,侵权必究,保留最终解释权!

     

    Description 

    Input

    包含6个用空格分割的m,a,c,X0,n和g,其中a,c,X0是非负整数,m,n,g是正整数。

    Output

    输出一个数,即Xn mod g

    Sample Input


    11 8 7 1 5 3


    Sample Output

    2
     
     
    正解:矩乘快速幂+快速乘法(or long double黑科技乘法)
    解题报告:
      就是一个矩乘裸题。  
      构造一个第一行为$[a,0]$,第二行为$[c,1]$,然后根据结合律,矩乘快速幂即可。
      开始我写的是快速乘法(龟速乘法),多了一个$log$。
      突然想起可以试试学过但是一直没用的$double$黑科技乘法,可以做到$O(1)$的$long$ $long$*$long$ $long$,写了一发,$WA$了很久之后终于发现我自己$yy$的是一个错的。
      转型太多导致精度爆炸了。
      考虑没有必要转过来转过去地做,可以用$long long$直接做,因为高位必然相等,而我只要$long long$部分的结果,而直接做相当于对$2^{64}$取模,没有问题...  
     
     
       龟速乘法:
     
    //It is made by ljh2000
    #include <iostream>
    #include <cstdlib>
    #include <cstring>
    #include <cstdio>
    #include <cmath>
    #include <algorithm>
    #include <ctime>
    #include <vector>
    #include <queue>
    #include <map>
    #include <set>
    #include <string>
    #include <complex>
    using namespace std;
    typedef long long LL;
    LL m,a,c,X0,n,g;
    struct Matrix{
    	LL s[2][2];
    }A,B,ini;
    
    inline LL cheng(LL x,LL y){
    	LL r=0;
    	while(y>0) {
    		if(y&1) r+=x,r%=m;
    		x+=x; x%=m;
    		y>>=1;
    	}
    	return r;
    }
    
    inline Matrix operator * (Matrix q,Matrix qq){
    	Matrix tmp=ini;
    	for(int i=0;i<2;i++)
    		for(int j=0;j<2;j++)
    			for(int l=0;l<2;l++)
    				tmp.s[i][j]+=cheng(q.s[i][l],qq.s[l][j]),tmp.s[i][j]%=m;
    	return tmp;
    }
    
    inline LL getLL(){
        LL w=0,q=0; char c=getchar(); while((c<'0'||c>'9') && c!='-') c=getchar();
        if(c=='-') q=1,c=getchar(); while (c>='0'&&c<='9') w=w*10+c-'0',c=getchar(); return q?-w:w;
    }
    
    inline void fast_pow(Matrix a,LL y){
    	B.s[0][0]=B.s[1][1]=1;
    	while(y>0) {
    		if(y&1) B=B*a;
    		a=a*a;
    		y>>=1;
    	}
    }
    
    inline void work(){
    	m=getLL(); a=getLL(); c=getLL(); X0=getLL(); n=getLL(); g=getLL();
    	A.s[0][0]=a; A.s[0][1]=0; A.s[1][0]=c; A.s[1][1]=1;
    	fast_pow(A,n);
    	printf("%lld",((cheng(X0,B.s[0][0])+B.s[1][0])%m)%g);
    }
    
    int main()
    {
        work();
        return 0;
    }
    

      

      long double 黑科技:

      

    //It is made by ljh2000
    #include <iostream>
    #include <cstdlib>
    #include <cstring>
    #include <cstdio>
    #include <cmath>
    #include <algorithm>
    #include <ctime>
    #include <vector>
    #include <queue>
    #include <map>
    #include <set>
    #include <string>
    #include <complex>
    using namespace std;
    typedef long long LL;
    LL m,a,c,X0,n,g;
    struct Matrix{
    	LL s[2][2];
    }A,B,ini;
    
    inline LL cheng(LL x,LL y){//double快速乘法
    	long double sum=(long double)x*y;
    	long double d=(long double)sum/m; LL zz=d+1e-6;//防止精度误差
    	LL r=x*y-zz*m; r%=m; r+=m; r%=m;//可以直接做,因为高位必然相等,而我只要long long部分的结果,而直接做相当于对2^64取模,没有问题
    	return r;
    }
    
    inline Matrix operator * (Matrix q,Matrix qq){
    	Matrix tmp=ini;
    	for(int i=0;i<2;i++)
    		for(int j=0;j<2;j++)
    			for(int l=0;l<2;l++)
    				tmp.s[i][j]+=cheng(q.s[i][l],qq.s[l][j]),tmp.s[i][j]%=m;
    	return tmp;
    }
    
    inline LL getLL(){
        LL w=0,q=0; char c=getchar(); while((c<'0'||c>'9') && c!='-') c=getchar();
        if(c=='-') q=1,c=getchar(); while (c>='0'&&c<='9') w=w*10+c-'0',c=getchar(); return q?-w:w;
    }
    
    inline void fast_pow(Matrix a,LL y){
    	B.s[0][0]=B.s[1][1]=1;
    	while(y>0) {
    		if(y&1) B=B*a;
    		a=a*a;
    		y>>=1;
    	}
    }
    
    inline void work(){
    	m=getLL(); a=getLL(); c=getLL(); X0=getLL(); n=getLL(); g=getLL();
    	A.s[0][0]=a; A.s[0][1]=0; A.s[1][0]=c; A.s[1][1]=1;
    	fast_pow(A,n);
    	printf("%lld",((cheng(X0,B.s[0][0])+B.s[1][0])%m)%g);
    }
    
    int main()
    {
        work();
        return 0;
    }
    

      

     
  • 相关阅读:
    钱多多软件制作04
    团队项目01应用场景
    HDU 4411 arrest
    HDU 4406 GPA
    HDU 3315 My Brute
    HDU 3667 Transportation
    HDU 2676 Matrix
    欧拉回路三水题 POJ 1041 POJ 2230 POJ 1386
    SPOJ 371 BOXES
    POJ 3422 Kaka's Matrix Travels
  • 原文地址:https://www.cnblogs.com/ljh2000-jump/p/6390657.html
Copyright © 2011-2022 走看看