2019牛客暑期多校训练营(第九场)I题 KM and M 类欧几里得

链接:https://ac.nowcoder.com/acm/contest/889/I
来源:牛客网
 

题目描述

输入N个M求

\sum_{k=1}^{N} ((KM)&M)mod(1e9+7)

输入描述:

The first and only line of input contains two space-separated integers, N, M (1 <= N <= 10^18, 1 <= M <= 10^11).

输出描述:

Output a single integer, the answer to the problem.

示例1

输入

4 6

输出

12

说明

The sum is 6 + 4 + 2 + 0 = 12.

题解:

算M每一个二进位上的贡献度,假设M二进制的第j位是1,假设 1M,2M,3M....NM中有x个数字第j位是1.

那么第j位二进制的贡献度就是 (1<<j)*x

那么现在的问题就是怎么能快速的求出1M,2M,3M....NM中有多少个数字第j位二进制是1

假设iM的二进制的第j位的求法为:\left \lfloor \frac{iM}{2^j} \right \rfloor - 2*\left \lfloor \frac{iM}{2^(j+1)} \right \rfloor

然后可以用类欧几里得分别算出等差数列的这两项之和。

参考博客:https://blog.csdn.net/WorldWide_D/article/details/54730588

代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod= 1e9 + 7;
const long long inv2=(mod+1)/2;
ll f(ll a,ll b,ll c,ll n){
    if (!a) return 0;
    ll x,y;
    if(a>=c||b>=c){
        x=f(a%c,b%c,c,n);
        y=((a/c)%mod*(n%mod)%mod*((n+1)%mod)%mod*inv2+b/c%mod*((n+1)%mod)+x)%mod;
        y=(y+mod)%mod;
        return y;
    }
    ll m=((__int128)a*n+b)/c;
    x=f(c,c-b-1,a,m-1);
    y=((__int128)n*m-x)%mod;
    y=(y+mod)%mod;
    return y;
}
int main(){
	ll n,m;
	cin>>n>>m;
	ll ans=0;
	for(int i=0;i<40;i++){
		if(m>>i&1){
			ll t=f(m,0,1LL<<i,n)-2*f(m,0,2LL<<i,n);
			t=(t%mod+mod)%mod;
			ans=(ans+(1LL<<i)%mod*t%mod)%mod;
		}
	}
	printf("%lld\n",ans);
    return 0;
}

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值