首先,可以按位考慮,對於第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;
}