某 SCOI 模拟赛 T1 迫害 DJ(hakugai)【二次剩余 斐波那契循环节】

题意

T T T 次询问:已知 a , b , n , k , m o d a,b,n,k,mod a,b,n,k,mod g 0 = a , g 1 = b , g i = g i − 1 + g i − 2 g_0=a,g_1=b,g_i=g_{i-1}+g_{i-2} g0=a,g1=b,gi=gi1+gi2 f ( n , k ) = { f ( g n , k − 1 ) ( k > 0 ) n ( k = 0 ) f(n,k)=\begin{cases}f(g_n,k-1)\quad&(k>0)\\n&(k=0)\end{cases} f(n,k)={f(gn,k1)n(k>0)(k=0),求 f ( n , k )   m o d   m o d f(n,k)\bmod mod f(n,k)modmod。不保证 m o d mod mod 为质数。 T ≤ 1 0 3 T\leq 10^3 T103 0 ≤ a , b < m o d ≤ 1 0 9 0\leq a,b<mod\leq10^9 0a,b<mod109 k ≤ 100 k\leq 100 k100

题解

题目也就是 g g g … g_{g_g\dots} ggg(套娃)。显然在套娃中直接模 m o d mod mod 会出问题,考虑套娃时应该模多少,也就是计算 g g g 在模某数时的循环节。

下文的 ( a b ) \left(\dfrac{a}{b}\right) (ba) 为勒让德符号。当 a , b a,b a,b 都为奇质数时,-1 代表 a a a 在模 b b b 下没有二次剩余,1 代表有二次剩余。

g g g 的特征方程为 r 2 = 3 r − 1 r^2=3r-1 r2=3r1 r 1 = 3 + 5 2 , r 2 = 3 − 5 2 r_1=\dfrac{3+\sqrt 5}{2},r_2=\dfrac{3-\sqrt 5}{2} r1=23+5 ,r2=235

其通项为 g i = C 1 r 1 i + C 2 r 2 i g_i=C_1r_1^i+C_2r_2^i gi=C1r1i+C2r2i

c i r ( n ) cir(n) cir(n) 为模 n n n 意义下 g g g 的循环节,我们要计算的就是 c i r cir cir,这样 g n   m o d   x = g n   m o d   c i r ( x ) m o d    x g_n\bmod x=g_{n\bmod cir(x)}\mod x gnmodx=gnmodcir(x)modx 可以大幅缩小数据范围。

小质数

手玩或者打表观察得: c i r ( 2 ) = 3 , c i r ( 3 ) = 8 , c i r ( 5 ) = 10 cir(2)=3,cir(3)=8,cir(5)=10 cir(2)=3,cir(3)=8,cir(5)=10

若 5 在模质数 p 下有二次剩余

判断时: ( 5 p ) ( p 5 ) = − 1 ( p − 1 ) ( 5 − 1 ) 4 \bigg(\dfrac{5}{p}\bigg)\bigg(\dfrac{p}{5}\bigg)=-1^{(p-1)(5-1)\over 4} (p5)(5p)=14(p1)(51),故该情况等价于 p p p 在模质数 5 下有二次剩余,即 p ≡ 1  或  4 ( m o d 5 ) p\equiv 1\text{ 或 }4\pmod 5 p1  4(mod5)

r 1 p = 1 2 p ( 3 + 5 ) p = 1 2 p ∑ i = 0 p 3 i 5 p − i ( p i ) = 1 2 p ( 3 p + 5 p ) = 3 + 5 2 = r 1 \begin{aligned} r_1^{p}=&{1\over 2^p}(3+\sqrt 5)^p\\ =&{1\over 2^p}\sum\limits_{i=0}^{p}3^i\sqrt 5^{p-i}{p \choose i}\\ =&{1\over 2^p}(3^p+\sqrt 5^p)\\ =&\dfrac{3+\sqrt 5}{2}=r_1 \end{aligned} r1p====2p1(3+5 )p2p1i=0p3i5 pi(ip)2p1(3p+5 p)23+5 =r1

( p i )   m o d   p {p \choose i}\bmod p (ip)modp 只在 i = 0 i=0 i=0 i = 1 i=1 i=1 时才不为 0)

(最后用的是费马小定理)

同理, r 2 p = r 2 r_2^p=r_2 r2p=r2

因此 g p = g 1 g_p=g_1 gp=g1。同理可推得 g p + 1 = g 2 g_{p+1}=g_{2} gp+1=g2,因此 c i r ( p ) ∣ p − 1 cir(p)\mid p-1 cir(p)p1,计算时取 c i r ( p ) = p − 1 cir(p)=p-1 cir(p)=p1

若 5 在模质数 p 下没有二次剩余

判断时: ( 5 p ) ( p 5 ) = − 1 ( p − 1 ) ( 5 − 1 ) 4 \bigg(\dfrac{5}{p}\bigg)\bigg(\dfrac{p}{5}\bigg)=-1^{(p-1)(5-1)\over 4} (p5)(5p)=14(p1)(51),故该情况等价于 p p p 在模质数 5 下没有二次剩余,即 p ≡ 2  或  3 ( m o d 5 ) p\equiv 2\text{ 或 }3\pmod 5 p2  3(mod5)

r 1 p = 1 2 p ( 3 + 5 ) p = 1 2 p ∑ i = 0 p 3 i 5 p − i ( p i ) = 1 2 p ( 3 p + 5 p ) = 3 + 5 p − 1 2 5 2 = 3 − 5 2 = r 2 \begin{aligned} r_1^{p}=&{1\over 2^p}(3+\sqrt 5)^p\\ =&{1\over 2^p}\sum\limits_{i=0}^{p}3^i\sqrt 5^{p-i}{p \choose i}\\ =&{1\over 2^p}(3^p+\sqrt 5^p)\\ =&\dfrac{3+5^{p-1\over 2}\sqrt 5}{2}\\ =&\dfrac{3-\sqrt 5}{2}=r_2 \end{aligned} r1p=====2p1(3+5 )p2p1i=0p3i5 pi(ip)2p1(3p+5 p)23+52p15 235 =r2

r 1 2 p + 2 = ( r 1 p ) 2 r 1 2 = r 2 2 r 1 2 = ( r 1 r 2 ) 2 = 1 \begin{aligned} r_1^{2p+2}=&(r_1^p)^2r_1^2\\ =&r_2^2r_1^2\\ =&(r_1r_2)^2=1 \end{aligned} r12p+2===(r1p)2r12r22r12(r1r2)2=1

同理 r 2 2 p + 2 = 1 r_2^{2p+2}=1 r22p+2=1。因此 g 0 = g 2 p + 2 g_0=g_{2p+2} g0=g2p+2,同理可推得 g 2 p + 3 = g 1 g_{2p+3}=g_{1} g2p+3=g1,因此 c i r ( p ) ∣ 2 p + 2 cir(p)\mid 2p+2 cir(p)2p+2,计算时取 c i r p = 2 p + 2 cir_p=2p+2 cirp=2p+2

合数

n = ∏ i p i a i n=\prod\limits_ip_i^{a_i} n=ipiai,则 c i r ( n ) = lcm ⁡ { c i r ( p i ) p i a i − 1 } cir(n)=\operatorname{lcm}\{cir(p_i)p_i^{a_i-1}\} cir(n)=lcm{cir(pi)piai1}


计算完每层的循环节大小就可以矩阵快速幂算了。循环节大小不会大过 long long O ( n ) O(\sqrt n) O(n ) 分解质因数也能跑过去(稍微实现得好一点是跑不满 O ( n ) O(\sqrt n) O(n ) 的,因为循环节变大时会引入许多 2 作为约数)。

#include<bits/stdc++.h>
using namespace std;
#define ll long long
int getint(){
	int ans=0,f=1;
	char c=getchar();
	while(c<'0'||c>'9'){
		if(c=='-')f=-1;
		c=getchar();
	}
	while(c>='0'&&c<='9'){
		ans=ans*10+c-'0';
		c=getchar();
	}
	return ans*f;
}

const int N=2;
ll x[N][N],ans[N][N];
ll tmp[N][N];
ll mod=0;
void qaqx(ll mod){
	for(int i=0;i<2;i++){
		for(int j=0;j<2;j++){
			tmp[i][j]=0;
			for(int k=0;k<2;k++){
				tmp[i][j]=(tmp[i][j]+x[i][k]*1ll*x[k][j]%mod)%mod;
			}
		}
	}
	for(int i=0;i<2;i++)for(int j=0;j<2;j++)x[i][j]=tmp[i][j];
}
void qaqans(ll mod){
	for(int i=0;i<2;i++){
		for(int j=0;j<2;j++){
			tmp[i][j]=0;
			for(int k=0;k<2;k++){
				tmp[i][j]=(tmp[i][j]+ans[i][k]*1ll*x[k][j]%mod)%mod;
			}
		}
	}
	for(int i=0;i<2;i++)for(int j=0;j<2;j++)ans[i][j]=tmp[i][j];
}
void qpow(ll y,ll mod){
	ans[0][0]=ans[1][1]=1;ans[1][0]=ans[0][1]=0;
	x[0][0]=0,x[0][1]=1,x[1][0]=mod-1,x[1][1]=3;
	while(y){
		if(y&1)qaqans(mod);
		qaqx(mod);
		y>>=1;
	}
}
ll gcd(ll x,ll y){
	return x?gcd(y%x,x):y;
}
ll cirp(ll p){
	if(p==2)return 3;
	if(p==5)return 10;
	return (p%5==2||p%5==3)?p*2+2:p-1;
}
ll cir(ll p){
	ll c=1;
	for(ll i=2;i*i<=p&&p!=1;i++){
		if(p%i==0){
			p/=i;
			ll d=1;
			d*=cirp(i);
			while(p%i==0)p/=i,d*=i;
			c=c/gcd(c,d)*d;
		}
	}
	if(p!=1)c=c/gcd(c,cirp(p))*cirp(p);
	//cerr<<"> "<<p<<" "<<c<<endl;
	return c;
}
ll g(ll a,ll b,ll n,ll p){
	qpow(n,p);
	return (a*1ll*ans[0][0]%p+b*1ll*ans[0][1]%p)%p;
}

ll q[233];
int main(){
	int T=getint();
	while(T--){
		ll a=getint(),b=getint(),n=getint(),k=getint(),p=getint();
		q[0]=p;
		for(int i=1;i<=k;i++)q[i]=cir(q[i-1]);n%=q[k];
		for(int i=k-1;i>=0;--i)n=g(a,b,n,q[i]);
		printf("%d\n",int(n));
	}
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值