OnlyPersistVictory DayThree

C

题意:
T T T组数据, f [ 0 ] = 0 , f [ 1 ] = 1 , f[0]=0,f[1]=1, f[0]=0,f[1]=1,每次给定 a , b a,b a,b,问 f [ a b ] m o d    n f[a^b]\mod n f[ab]modn的值。
数据范围: 1 ≤ T ≤ 10000 , 0 ≤ a , b < 2 64 , 1 ≤ n ≤ 1000 1\leq T\leq 10000, 0\leq a,b<2^{64},1\leq n\leq 1000 1T10000,0a,b<264,1n1000

题解:
考虑对 n n n取模,则 f f f最多有 n n n种取值,且最多有 n 2 n^2 n2种组合后,就会出现重复的组合,那么此后的 f i f_i fi将会相同,形成一个循环。因此我们只需要去枚举第一次出现循环的位置即可,即第一次出现 f [ i ] = f [ 1 ] , f [ i − 1 ] = f [ 0 ] , i ≥ 1 f[i]=f[1],f[i-1]=f[0],i\geq 1 f[i]=f[1],f[i1]=f[0],i1后, i − 1 i-1 i1即一个周期的长度。
f [ a b m o d    i ] m o d    n f[a^b\mod i]\mod n f[abmodi]modn即为所求。注意特判 0 0 0的情况。

代码:

#include<bits/stdc++.h>
using namespace std;

typedef unsigned long long ll;

const int N = 1000010;
int f[N];
ll a, b;
int n, m;

int qp(ll a, ll b, ll mod) {
	ll ans = 1 % mod;
	while(b) {
		if(b & 1) ans = ans * a % mod;
		a = a * a % mod;
		b >>= 1;
	}	
	return ans;
}

void solve() {
	scanf("%llu%llu%d", &a, &b, &n);
	if(a == 0 || n == 1) {
		puts("0");
		return ;
	}
	f[0] = 0, f[1] = 1 % n;
	int len = 0, m = n * n + 1;
	for(int i = 2; i <= m; ++i) { 
		f[i] = (f[i - 1] + f[i - 2]) % n;
		if(f[i] == f[1] && f[i - 1] == f[0]) {
			len = i - 1;
			break;
		}
	}
	
	if(len == 0) printf("%d\n", f[0]);
	else printf("%d\n", f[qp(a % len, b, len)]);
}

int main()
{
	int T;
	scanf("%d", &T);
	for(int i = 1; i <= T; ++i) solve();

	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值