循环节+矩阵快速幂 HDU4291

循环节其实就可以看做取模,一般的1e9 + 7其实就是个循环节,只是大了点……

切入正题 HDU4291

  1. g(x)很明显的矩阵快速幂
  2. 本地直接暴力找循环节
    ll a = 0, b = 1;
    for(int i = 2; ; ++i){
    	printf("%d  ", i);
    	a = (3 * b + a) % MOD;
    	//swap(a, b);  位运算更快 
    	a = a ^ b;
    	b = a ^ b;
    	a = a ^ b; 
    	if(a == 0 && b == 1) printf("Mod= %d\n", i);
    }

    一定要 开 long long !!!  我没开 long long 卡了一个多小时呜呜呜呜呜

  3. 三个g嵌套,就分了三个循环节

我最开始没有把循环节的概念弄清楚,写成了这样

	n = quickpoww(n % Mod3).m[0][1];//g(g(g(x)))的循环节为 MOD3
	n = quickpoww(n % Mod2).m[0][1];//g(g(x)) 的循环节为 MOD2 
	n = quickpoww(n % Mod1).m[0][1];//g(x)的循环节为MOD1 

在得到循环节的情况下快速幂直接对1e9+7取模

自然就……

其实仔细一想,对变量取模就是利用了当前函数的循环节,而对于当前函数对外面一层的函数(嵌套情况下)的循环节则是对函数值(此时已是作为变量)取模。

例如,对于g(g(g(x))),x循环节为240,而x240取模后算出的g(x)在函数g(g(g(x)))中的循环节则是183120,即第二层取模应取183120。至于1e9+7,它只不过是最外面一层函数的循环节

 

while(scanf("%lld", &n) != EOF){
		n = quickpoww(n % Mod3, Mod2).m[0][1];//g(g(g(x)))的循环节为 MOD3
		n = quickpoww(n % Mod2, Mod1).m[0][1];//g(g(x)) 的循环节为 MOD2 
		n = quickpoww(n % Mod1, Mod0).m[0][1];//g(x)的循环节为MOD1 
		printf("%lld\n", n);
	}

其实1e9+7也不过是最外面一层的循环节而已,不能当成“万能取模”随便用到快速幂里面,对于不同的循环节有不同的模值。

最后AC代码:

#include<bits/stdc++.h>
#define ll long long
#define MAXN 2
static const int Mod0 = 1000000007;
static const int Mod1 = 222222224;
static const int Mod2 = 183120;
static const int Mod3 = 240;
using namespace std;
typedef struct Matrix{
	ll m[MAXN][MAXN];
}Matrix;
Matrix mat_muti(Matrix a, Matrix b, int mod){
	Matrix ans;
	for(int i = 0; i < MAXN; i++)
	for(int j = 0; j < MAXN; j++){
		ans.m[i][j] = 0;
		for(int k = 0; k < MAXN; k++) ans.m[i][j] = (ans.m[i][j] + a.m[i][k] * b.m[k][j]) % mod;
	}
	return ans;
}
Matrix quickpoww(int n, int mod){
	Matrix ans, base;
	ans.m[0][0] = 1; ans.m[0][1] = ans.m[1][0] = ans.m[1][1] = 0;
	base.m[0][0] =  3; base.m[1][1] = 0; base.m[1][0] = base.m[0][1] = 1;
	while(n > 0){
		if(n & 1) ans = mat_muti(ans, base, mod);
		base = mat_muti(base, base, mod);
		n >>= 1;
	}
	return ans;
}
int main(){
	ll n;
	while(scanf("%lld", &n) != EOF){
		n = quickpoww(n % Mod3, Mod2).m[0][1];//g(g(g(x)))的循环节为 MOD3
		n = quickpoww(n % Mod2, Mod1).m[0][1];//g(g(x)) 的循环节为 MOD2 
		n = quickpoww(n % Mod1, Mod0).m[0][1];//g(x)的循环节为MOD1 
		printf("%lld\n", n);
	}
	return 0;
} 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值