正题
题目链接:https://www.luogu.com.cn/problem/P5137
题目大意
TTT组数据给出n,a,b,pn,a,b,pn,a,b,p求
(∑0=1naibn−i)%p\left(\sum_{0=1}^na^ib^{n-i}\right)\%p(0=1∑naibn−i)%p
1≤T≤105,1≤n,a,b,p≤10181\leq T\leq 10^5,1\leq n,a,b,p\leq 10^{18}1≤T≤105,1≤n,a,b,p≤1018
解题思路
这个数据很大,考虑倍增求。
设为答案f(n)f(n)f(n),那么有
f(n)=f(n2)(an2+bn2)−an2bn2f(n)=f(\frac{n}{2})(a^{\frac{n}{2}}+b^{\frac{n}{2}})-a^{\frac{n}{2}}b^{\frac{n}{2}}f(n)=f(2n)(a2n+b2n)−a2nb2n
f(n)=af(n−1)+bnf(n)=af(n-1)+b^{n}f(n)=af(n−1)+bn
倍增维护就好了
时间复杂度O(Tlogn)O(T\log n)O(Tlogn)
code
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cctype>
#define ll long long
using namespace std;
ll n,a,b,p,T;
ll read(){ll x=0,f=1;char c=getchar();while(!isdigit(c)){if(c=='-')f=-f;c=getchar();}while(isdigit(c)){x=(x<<1)+(x<<3)+c-'0';c=getchar();}return x*f;
}
ll fac(ll a,ll b){ll c=(long double)a*b/p;long double ans=a*b-c*p;if(ans>=p)ans-=p;else if(ans<0)ans+=p;return ans;
}
signed main()
{T=read();while(T--){n=read();a=read();b=read();p=read();ll ans=1,k=0,B=1,A=1;for(ll i=62;i>=0;i--){ans=(fac(A,ans)+fac(B,ans))%p;ans=(ans+p-fac(A,B))%p;k*=2;B=fac(B,B);A=fac(A,A);if((n>>i)&1){k++;B=fac(B,b);A=fac(A,a);ans=(fac(ans,a)+B)%p;}}printf("%lld\n",ans);}return 0;
}