题目
给定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;
}