我们可以旋转串T,使得l~r等价于0~r-l
根据(r-l)%k可以将T分成T1,T2两部分,问题变成满足
0<=a<2|T1|,0<=b<2|T2|
,
pa+qb≡x(Mod p)
的解数
也即
0<=a<A,0<=b<B
记
A=k1p+ka,B=k2p+kb
,当
ka
或
kb
等于0的时候比较好讨论不在此处赘述,下面讨论
ka,kb≠0
的情况
当
0<=a<k1p
时,对于任意一个b,都有k1个a与之对应
当
k1p<=a<k1p+ka,0<=b<k2p
时,对于任意一个a,都有k2个b与之对应
所以我们不妨设 0<=a<ka,0<=b<kb (ka,kb<p)
画一下柿子
a+qpb≡xp(Mod p)
kb≡[l,r)(Mod p)
然后有个结论:
ϵ(x≡[l,r)(Mod p)=[x−lp]−[x−rp](l<r)
于是
ans=∑kb−1b=0[kb−lp]−∑kb−1b=0[kb−rp]
然后就是一个类欧几里得了
然后..就没了…什么你问我为什么写的这么长??当然是因为…zzdsy不滋滋int128啊….要手写高精啊
code:
#include<set>
#include<map>
#include<deque>
#include<queue>
#include<stack>
#include<cmath>
#include<ctime>
#include<bitset>
#include<string>
#include<vector>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<climits>
#include<complex>
#include<iostream>
#include<algorithm>
#define ll long long
using namespace std;
ll mul(ll a,ll b,ll mod)
{
if(a>=mod) a%=mod;
if(b>=mod) b%=mod;
ll re=0;
while(b)
{
if(b&1) re=(re+a)%mod;
a=(a+a)%mod;
b>>=1;
}
return re;
}
ll pw(ll x,ll k,ll mod)
{
if(x>=mod) x%=mod;
ll re=1ll;
for(;k;k>>=1,x=mul(x,x,mod)) if(k&1ll)
re=mul(re,x,mod);
return re;
}
ll inv(ll x,ll mod) { return pw(x,mod-2,mod); }
ll sum(ll n,ll mod) { return mul(mul(n,n+1ll,mod),inv(2ll,mod),mod); }
const ll bit = 1e18;
int use[40],tp;
struct bignum
{
ll a,b;
void build(bignum x)
{
while(tp) use[tp--]=0;
for(int i=1;i<=18&&x.b;i++)
use[i]=x.b%10,x.b/=10ll;
for(int i=19;i<=36&&x.a;i++)
use[i]=x.a%10,x.a/=10ll;
tp=36; while(!use[tp]) tp--;
}
void div(bignum &x)
{
ll cc=x.a&1; x.a>>=1;
cc*=bit; cc+=x.b; x.b=cc>>1;
}
friend inline bool operator ==(const bignum &x,const bignum &y){return x.a==y.a&&x.b==y.b;}
friend inline bool operator <(const bignum &x,const bignum &y){return x.a<y.a||(x.a==y.a&&x.b<y.b);}
friend inline bool operator >(const bignum &x,const bignum &y){return x.a>y.a||(x.a==y.a&&x.b>y.b);}
friend inline bignum operator +(const bignum &x,const bignum &y)
{
ll cc=x.b+y.b;
return (bignum){x.a+y.a+cc/bit,cc%bit};
}
friend inline bignum operator -(const bignum &x,const bignum &y)
{
ll cc=x.b-y.b;
return cc<0?(bignum){x.a-y.a-1,cc+bit}:(bignum){x.a-y.a,cc};
}
};
bignum zero,one,two,ten;
bignum bigmul(bignum x,bignum y)
{
bignum re=zero,temp;
while(!(y==zero))
{
if(y.b&1ll) re=re+x;
x=x+x;
temp.div(y);
}
return re;
}
bignum bigmulmod(bignum x,bignum y,const bignum &mod)
{
bignum re=zero,temp;
while(!(y==zero))
{
if(y.b&1ll)
{
re=re+x;
if(re>mod||re==mod) re=re-mod;
}
x=x+x; if(x>mod||x==mod) x=x-mod;
temp.div(y);
}
return re;
}
inline bignum operator /(const bignum &x,const bignum &y)
{
bignum cc; cc.build(x);
bignum re=zero,now=zero;
for(int i=tp;i>=1;i--)
{
now=bigmul(now,ten); now=now+(bignum){0ll,use[i]};
re=bigmul(re,ten);
while(now>y||now==y) now=now-y,re=re+one;
}
return re;
}
bignum bigpow(bignum x,ll k,const bignum &mod)
{
bignum re=one;
for(;k;k>>=1,x=bigmulmod(x,x,mod)) if(k&1ll)
re=bigmulmod(re,x,mod);
return re;
}
bignum Mod;
const ll mod = 1e9+7;
ll p,x,l,r,k;
ll c1,c2,T1,T2;
ll cal(ll a,ll b,ll c,ll n)
{
if(n<0) return 0;
ll re=0;
if(a<0)
{
ll tmp=(c-1-a)/c; re-=tmp%mod*sum(n,mod)%mod;
a+=tmp*c;
}
if(a>=c)
{
ll tmp=a/c; re+=tmp%mod*sum(n,mod)%mod;
a-=tmp*c;
}
if(b<0)
{
ll tmp=(c-1-b)/c; re-=tmp%mod*((n+1ll)%mod)%mod;
b+=tmp*c;
}
if(b>=c)
{
ll tmp=b/c; re+=tmp%mod*((n+1ll)%mod)%mod;
b-=tmp*c;
}
if(!a||!n) return re;
bignum t1=(bignum){0ll,a},t2=(bignum){0ll,n},t3=(bignum){0ll,b};
t1=bigmul(t1,t2); t1=t1+t3; t1=t1/(bignum){0ll,c};
ll m=t1.b;
re+=n%mod*(m%mod)%mod;
re-=cal(c,c-b-1,a,m-1);
re=(re%mod+mod)%mod;
return re;
}
ll solve0()
{
ll ans=0;
if(!c1) ans=!x?pw(2ll,T1,mod):0ll;
else
{
x=mul(x,inv(c1,p),p);
bignum Qa=bigpow(two,T1,Mod); Qa=Qa/(bignum){0ll,p}; ll qa=Qa.b;
ll ka=pw(2ll,T1,p);
ans=qa; if(ka>=x) ans++;
}
ans=(ans%mod+mod)%mod;
ans=ans*pw(2ll,T2,mod)%mod;
return ans;
}
ll solve()
{
if(!c1) swap(c1,c2),swap(T1,T2);
if(!c2) return solve0();
ll ans=0;
bignum Qa=bigpow(two,T1,Mod); Qa=Qa/(bignum){0ll,p}; ll qa=Qa.b;
ll ka=pw(2ll,T1,p);
ans=qa%mod*pw(2ll,T2,mod)%mod;
bignum Qb=bigpow(two,T2,Mod); Qb=Qb/(bignum){0ll,p}; ll qb=Qb.b;
ll kb=pw(2ll,T2,p);
ans=(ans+(qb%mod)*(ka%mod)%mod)%mod;
if(ka&&kb)
{
ll cc=inv(c1,p); c2=mul(c2,cc,p); x=mul(x,cc,p);
ans=(ans+cal(-c2,x,p,kb-1))%mod;
ans=(ans-cal(-c2,x-ka,p,kb-1)+mod)%mod;
}
return ans;
}
int main()
{
zero.a=zero.b=0ll;
one.a=0,one.b=1ll;
two.a=0,two.b=2ll;
ten.a=0,ten.b=10ll;
int tcase=0;
while(scanf("%lld%lld%lld%lld%lld",&p,&x,&l,&r,&k)!=EOF&&p)
{
Mod=bigmul((bignum){0ll,p},(bignum){0ll,mod});
r=r-l+1;
if(r<=k)
{
T1=r,T2=k-r;
c1=1,c2=0;
}
else if(r%k==0)
{
T1=k,T2=0;
ll t1=pw(2ll,r,p); t1=(t1-1+p)%p;
ll t2=pw(2ll,k,p); t2=(t2-1+p)%p;
if(t2) t1=mul(t1,inv(t2,p),p);
else t1=r/k;
c1=t1,c2=0;
}
else
{
T1=r%k,T2=k-T1;
ll t1=pw(2ll,(r/k+1)*k,p); t1=(t1-1+p)%p;
ll t2=pw(2ll,k,p); t2=(t2-1+p)%p;
if(t2) c1=mul(t1,inv(t2,p),p);
else c1=r/k+1;
t1=pw(2ll,r/k*k,p); t1=(t1-1+p)%p; ll cc=pw(2ll,T1,p); t1=mul(t1,cc,p);
t2=pw(2ll,k,p); t2=(t2-1+p)%p;
if(t2) c2=mul(t1,inv(t2,p),p);
else c2=mul(cc,r/k,p);
}
printf("Case #%d: %lld\n",++tcase,solve());
}
return 0;
}