zoukankan      html  css  js  c++  java
  • 关于斐波那契数模意义下的循环节问题

    123456

    (f(f(n)))(f)表示斐波那契数
    (nleq10^{100})
    对于(1e9+7)取mod
    斐波那契数在mod意义下是有循环节的,
    然后zhx把他出在了noip模拟题里,
    丧心病狂,

    丢一个paper
    Charles W. Campbell II. The Period of the Fibonacci Sequence Modulo j. 2007.

    找循环节的算法大致是
    把模数质n因数分解,分解为$ p_1 ^ {k_1} * p_2^ {k_2} *...p_n^{k_n} ( 对于%n意义下的循环节就是) lcm (mod (质因数 ^ k) 意义下的循环节 ) $
    那么后面那个怎么求呢
    有定理

    (fib数 mod p^m) 的最小循环节长度为 (G(p) * p^{m - 1})其中,(G(p))表示(%p)的最小循环节长度

    现在就是求(G(p))
    对于(G(p))我们有如下定理

    如果(5)是模(p)的二次剩余那么循环节的长度是(p-1)的因子否则长度为(2(p + 1))
    二次剩余及计算方法
    对于小于等于5的素数特殊判断,loop(2)=3,loop(3)=8,loop(5)=20。

    可以求出所有的因子,然后用矩阵快速幂来一个一个判断,这样时间复杂度不会很大。

    本题模数只有一个,手玩就好了

    代码

    #include<cstdio> 
    #include<cstring> 
    #include<algorithm> 
    
    using namespace std; 
    #define int long long 
    inline int read() { 
    	int x = 0,f = 1; 
    	char c = getchar(); 
    	while(c  < '0' || c > '9') c = getchar(); 
    	while(c  <= '9' && c >= '0') x = x * 10 + c-'0',c = getchar(); 
    	return x *f ; 
    } 
    const int m1 = 1000000007; 
    const int m2 = m1 * 2 + 2; 
    const int m3 = m2 * 3; 
    int n ; 
    struct Matrix { 
    	int a[3][3]; 
    	Matrix () { memset(a,0,sizeof a); }   	
    	Matrix  operator * (const Matrix & p) const { 
    		Matrix ret; 
    		for(int i = 0;i <= 1;++ i) 
    			for(int j = 0;j <= 1;++ j) 
    				for(int k = 0;k <= 1;++ k) 
    					ret.a[i][j] = (ret.a[i][j] + a[i][k] * p.a[k][j]) % m1; 
    		return ret; 
    	} 
    	Matrix  operator + (const Matrix & p) const {
    		Matrix ret; 
    		for(int i = 0;i <= 1;++ i) 
    			for(int j = 0;j <= 1;++ j) 
    				for(int k = 0;k <= 1;++ k) 
    					ret.a[i][j] =(ret.a[i][j] +  a[i][k] * p.a[k][j]) % m2; 
    	 	return ret; 
    	} 
    }; 
    int get1(int x) { 
    	Matrix p,q; 
    	p.a[0][0] = 1; p.a[0][1] = 1; p.a[1][0] = 1; 
    	q.a[0][1] = 1;//,q.a[1][1] = 1; 
    	for(;x;x >>= 1,p = p + p) 
    		if(x & 1) q = q + p; 
    	return q.a[0][0]; 
    } 
    int get2(int x) { 
    	Matrix p,q; 
    	p.a[0][0] = 1; p.a[0][1] = 1; p.a[1][0] = 1; 
    	q.a[0][1] = 1;  
    	for(;x;x >>= 1,p = p * p) 
    		if(x & 1) q = q * p; 
    	return q.a[0][0]; 
    } 
    char s[100007]; 
    struct bign { 
    	int z[100007],l;
    	void init() { 
     		memset(z,0,sizeof(z)); 
    		scanf("%s",s + 1); 
    		l = strlen(s + 1); 
    		for(int i = 1;i <= l;i ++) 
    			z[i] = s[l - i + 1] - '0'; 
    	} 
    	int operator % (const long long & a) const { 
    		int b = 0; 
    		for (int i = l;i >= 1;i --) 
    			b = (b * 10 + z[i]) % a; 
    		return b; 
    	} 
    }z;  
    main() { 
    	int t = read(); 
    	bign num; 
    	while(t --)  { 
    		num.init(); 
    		n = num % m3; 
    		n = get1(n); 
    		printf("%lld
    ",get2(n));  
    	} 	
    	return 0; 
    } 
    /* 
    
    */ 
    
  • 相关阅读:
    git 远程仓库的使用
    git 以及 工作区 版本库 暂存区
    git repo gerrit 的关系
    【转】c# delegate
    【转】分析.net中的object sender与EventArgs e
    如果plsql连接没问题,但程序中报ORA-12504的错误
    【转】C# String 与 Char[] 数组 相互转换
    【转】C#日期时间格式化
    PLSQL导出语句的查询结果
    oracle取order by的第一条数据
  • 原文地址:https://www.cnblogs.com/sssy/p/9418732.html
Copyright © 2011-2022 走看看