首先,可以按位考虑,对于第i位有多少个m的倍数满足这一位上为1?
对于一个数x,我们判断这一位上是否为1,参考十进制的做法,即 ;
那么将公式变一下型:
后半部分是一个等差数列整除一个整数的求和式。
很久之前就存过这个板子了,但比赛时还是不会做。。。。
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define lll __int128
#define mod 1000000007
//a 公差 b 首项 c 除数 n 项数
lll get(lll a,lll b,lll c,lll n){
if (n<=0) return 0;
if (n==1) return (b/c)%mod ;
lll tmp = 0;
tmp +=(lll)(a/c)*(n-1)%mod*n/2%mod+ (lll)b/c*n%mod;
tmp%=mod;
a = a%c;
b = b%c;
if (a==0) return tmp;
return (tmp+get(c,(a*n+b)%c,a,(a*n+b)/c))%mod;
}
int main()
{
ll n,m,ans=0;
cin>>n>>m;
for(int i=0;i<40;i++){
if(m&(1ll<<i)){
ll t=get(m,0,1ll<<i,n)-2*get(m,0,2ll<<i,n);
t=(t%mod+mod)%mod;
ans=(ans+(1ll<<i)%mod*t%mod)%mod;
}
}
cout<<ans<<endl;
return 0;
}