题目:
题意:
输入N,M,求下列式子的值:
笔记:
考虑对M的每一位算贡献,假设M的第x位为1,那么计算这一位的贡献就等价于计算KM中有多少个数的第x位为1,计算一个数第x位的值是多少可以这样计算:(v>>x) - (v>>(x+1))*2,那么第x位的贡献为:
上面求和式就是类欧几里得的模板
代码:
#include <bits/stdc++.h>
using namespace std;
typedef __int128 LL;
const int mod = 1e9+7;
const int inv2 = 500000004;
inline LL read(){
LL x = 0,f = 1; char c = getchar();
while(!isdigit(c)){if(c=='-') f=-1;c=getchar();}
while(isdigit(c)){x=x*10+(c-'0');c = getchar();}
return x*f;
}
inline void write(LL x){
if(x < 0) putchar('-'),x = -x;
if(x > 9) write(x/10);
putchar(x%10+'0');
}
LL solve(LL a,LL b,LL c,LL n){ //计算(a*0+b)/c+(a*1+b)/c+...+(a*n+b)/c
if(a == 0) return b/c%mod*(n+1)%mod;
if(a>=c || b>=c) return solve(a%c,b%c,c,n)+n%mod*(n+1)%mod*inv2%mod*(a/c)%mod+(n+1)%mod*(b/c)%mod;
LL m = (a*n+b)/c;
return (n%mod*m%mod-solve(c,c-b-1,a,m-1)+mod)%mod;
}
int main(){
LL n,m,ans = 0;n = read(),m = read();
for(int i = 0;i < 50;++i){
if(m&(1ll<<i)){
ans += (1ll<<i)%mod*(solve(m,0,1ll<<i,n)%mod-2ll*solve(m,0,1ll<<(i+1),n)%mod+mod)%mod;
if(ans >= mod) ans -= mod;
}
}
write((ans%mod+mod)%mod);
return 0;
}