hdu 2818 Interesting Fibonacci 斐波那契 循環節

傳送門

題目大意:就是給你兩個函數,一個是F(n) = F(n-1) + F(n-2),
F(0) = 0, F(1) = 1;
另一個是 G(n) = G(n-1)^F(a^b);
G(1) = F(a^b);
求G(n) % c;
範圍:A, B, N, C (10<=A, B<2^64, 2<=N<2^64, 1<=C<=300)

注意了:c的範圍是1<= C <= 300,所以說它一定會有循環 節:
解題思路: 首先算G(1) = F(a^b),設a^b的循環節是len;
F(a^b)%c = F(a^b%len)%c;
一邊加一邊取餘

然後算G(n)%c = F(a^b)^(F(a^b)^(n-1)) % c;
G(n)%c = F(a^b)^(F(a^b)^(n-1)%phi(c)+phi(c))%c;
F(a^b)^(n-1)%phi(c)+phi(c) == (F(a^b)%phi(c)^(n-1))+phi(c)
F(a^b)%phi(c) 有循環節

 

#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <math.h>
#define ll unsigned long long
using namespace std;
ll f[90005];
ll power(ll a,ll b,ll mod)
{
    ll ans=1;
    a=a%mod; // !!注意
    while(b)
    {
        if(b&1)
            ans=ans*a%mod;
        a=a*a%mod;
        b>>=1;
    }
    return ans;
}
ll lala(ll n)
{
	ll ans=n;
	for(ll i=2;i*i<=n;i++)
	{
		if(n%i==0)
		{
			ans=ans/i*(i-1);// φ(N)=N*(1-1/P1)*(1-1/P2)*...*(1-1/Pn) 公式
			while(n%i==0)
			{
				n/=i;
			}
		}
	}
	if(n>1)
	ans=ans/n*(n-1);
	return ans;
}
ll loop(ll m)
{
    f[0]=0;
    f[1]=1;
    f[2]=1;
    for(ll i=3;;i++)
    {
        f[i]=(f[i-1]+f[i-2])%m;
        if(f[i]==f[1]&&f[i-1]==f[0])
        {
            return i-1;
        }
    }
}
int main()
{
    int t;
    cin>>t;
    int cnt=0;
    while(t--)
    {
        ll a,b,n,c;
        cin>>a>>b>>n>>c;
        printf("Case %d: ",++cnt);
        if(c==1)
        {
            cout<<0<<endl;
            continue;
        }
        ll ph=lala(c);
        ll l=loop(c);
        ll cur=power(a,b,l);
        cur=f[cur];
        if(ph==1) // 歐拉值爲1時特判
        {
            cout<<power(cur,ph,c)<<endl;
            continue;
        }
        l=loop(ph);
        ll sum=power(a,b,l);
        sum=f[sum];
        sum=power(sum,n-1,ph)+ph;
        cur=power(cur,sum,c);
        cout<<cur<<endl;
    }
    return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章