您的位置:首页 > 其它

BZOJ 3240 [Noi2013]矩阵游戏 ——费马小定理 快速幂

2017-03-19 20:39 309 查看

发现是一个快速幂,然而过不去。

怎么办呢?

1.十进制快速幂,可以用来练习卡时。

2.费马小定理,如果需要乘方的地方,可以先%(p-1)再计算,其他地方需要%p,所以需要保存两个数。

然后就是分类讨论a是否为1(等比数列求和时要求a不为1)

然后就是递推了。

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;

#define F(i,j,k) for (ll i=j;i<=k;++i)
#define D(i,j,k) for (ll i=j;i>=k;--i)
#define ll long long
const ll md=1000000007;
ll n1,m1,n2,m2,a,b,c,d,len,ans;
char s1[1000005],s2[1000005];
ll qpow(ll a,ll b)
{
ll ret=1;
while (b)
{
if (b&1) (ret*=a)%=md;
(a*=a)%=md;
b>>=1;
}
return ret;
}
ll inv(ll a)
{return qpow(a,md-2);}
int main()
{
scanf("%s",s1+1);
scanf("%s",s2+1);
len=strlen(s1+1); F(i,1,len) n1=(n1*10+s1[i]-'0')%(md-1);
len=strlen(s2+1); F(i,1,len) m1=(m1*10+s2[i]-'0')%(md-1);
len=strlen(s1+1); F(i,1,len) n2=(n2*10+s1[i]-'0')%md;
len=strlen(s2+1); F(i,1,len) m2=(m2*10+s2[i]-'0')%md;
scanf("%lld%lld%lld%lld",&a,&b,&c,&d);
if (a!=1)
{
ll e,f;
e=(qpow(a,m1-1)*c)%md;
f=(((((qpow(a,m1-1)-1+md)%md*b)%md*c)%md*inv(a-1))%md+d)%md;
if (e==1)
{
ll tmp=(1LL+f*n2)%md;
ans=((tmp-d+md)%md*inv(c))%md;
}
else
{
ll tmp=qpow(e,n1)+(((qpow(e,n1)-1+md)%md*f)%md*inv((e-1+md)%md))%md;
ans=((tmp-d+md)%md*inv(c))%md;
}
}
else
{
ll e,f;
e=c; f=(((c*b)%md*(m2-1))%md+d)%md;
if (e==1)
{
ll tmp=(1LL+f*n2)%md;
ans=((tmp-d+md)%md*inv(c))%md;
}
else
{
ll tmp=qpow(e,n1)+(((qpow(e,n1)-1+md)%md*f)%md*inv((e-1+md)%md))%md;
ans=((tmp-d+md)%md*inv(c))%md;
}
}
printf("%lld\n",ans);
}

  

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: