題目
給定t(t<=1e5),x,y(1<=x<=y<=1e18),求,輸出和式對1e9+7取模的值
其中,爲1到i^k異或的值
思路來源
https://www.cnblogs.com/bringlu/p/12578504.html
官方題解
題解
假酒警告:發現了自己原來的板子在拉格朗日差值部分會爆ll
首先,根據異或這個0123異或起來得0,且逢4就異或得0的性質,可得,
所以可以化簡,把x項放前面,1項放後面,
注意到顯然與等價,有下式
討論的值,實際上是討論的值,搞出後面那項
①i%4==1,次冪模4意義下呈1 1 1 1,全1分佈
②i%4==2,呈2 0 0 0分佈,第一個是2後面全是0
③i%4==3,呈3 1 3 1分佈,31交替分佈
④i%4==0,呈0 0 0 0分佈,全0分佈
然後考慮前面這項,由於要求是偶數,先提一個2出來
,
形如的式子怎麼求,
如果直接暴力對內部和式插值,再對外部枚舉k,複雜度是的,不能接受
考慮交換枚舉順序,這樣裏面是個等比數列,
由於f(i)是最高次冪t+1次的多項式,因此和函數S(i)是t+2次的,
先求出S(i)前t+2項,即下標0到t+1的值,代入m對應的插值即可
代碼
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod=1e9+7;
const int N=1e5+10;
int t;
int sum[N],pre[N],suf[N];
int fac[N],finv[N];
ll x,y,res;
int modpow(int x,int n,int p){
int res=1;
for(;n;x=1ll*x*x%p,n>>=1)
if(n&1)res=1ll*res*x%p;
return res;
}
//已知f[0]到f[mx] 求f[n]
int cal(int *f,int mx,int n){
if(n<=mx)return f[n];
int ans=0;
pre[0]=suf[mx]=1;
for(int i=1;i<=mx;++i)
pre[i]=1ll*(n-i+1)%mod*pre[i-1]%mod;
for(int i=mx;i>=1;--i)
suf[i-1]=1ll*(n-i)%mod*suf[i]%mod;
for(int i=0;i<=mx;++i){
int sg=(mx-i)&1?-1:1;
ans=ans+1ll*sg*pre[i]%mod*suf[i]%mod*finv[i]%mod*finv[mx-i]%mod*f[i]%mod;
if(ans>=mod)ans-=mod;
if(ans<0)ans+=mod;
}
return ans;
}
void init(){
fac[0]=1;
for(int i=1;i<N;++i)
fac[i]=1ll*fac[i-1]*i%mod;
finv[N-1]=modpow(fac[N-1],mod-2,mod);
for(int i=N-1;i>=1;--i)
finv[i-1]=1ll*finv[i]*i%mod;
}
ll cal(ll l,ll r,int a){//[l,r]裏有多少%4==a
ll y=(r-a+4)/4,x=(l-1-a+4)/4;//和0對齊 +4是爲了統一r<a的情況 找找規律
return (y-x+mod)%mod;
}
int main(){
init();
scanf("%d%lld%lld",&t,&x,&y);
sum[0]=0;
for(int i=1;i<=t+1;++i){//t+1次多項式 代入0到t+1次冪 共t+2個值
sum[i]=(sum[i-1]+(1ll*modpow(2*i,t+1,mod)-2*i+mod)%mod*modpow(2*i-1,mod-2,mod)%mod)%mod;
}
res=(cal(sum,t+1,y/2)-cal(sum,t+1,(x-1)/2)+mod)%mod;
res=(res+t*cal(x,y,1)%mod)%mod;//不管k爲何值 i%4==1 都有(i^k)%4==1 呈 1 1 1 1分佈
res=(res+cal(x,y,2)%mod)%mod;//僅有k=1時 i%4==2 有(i^k)%4==2 呈 2 0 0 0 分佈
res=(res+t/2*cal(x,y,3)%mod)%mod;//i%4==3 都有(i^k)%4==1 呈 3 1 3 1分佈
printf("%lld\n",res);
return 0;
}