Description
给出如下形式的等差数列:
B+A,B+2A,B+3A,...,B+NA
求每一项化成二进制后,一共有多少位
1
。
Data Constraint
Solution
拆位考虑答案贡献。
考虑第
i
位的贡献。
我们知道一个数
于是我们第
i
位的答案贡献可以表示成
看一下,这不就是裸的类欧几里得算法吗?
直接上板子。
注意到答案并没有要求取模,所以在实现时需要把模数设为一个一定比答案大的数即可。
Code
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define fo(i,j,l) for(int i=j;i<=l;++i)
#define fd(i,j,l) for(int i=j;i>=l;--i)
using namespace std;
typedef long long ll;
const ll mo=1e14;
ll n,m,j,k,l,i,o,p;
ll A,B,N;
int tt;
ll times(ll a,ll b)
{
ll y=0;
for(;a;a>>=1,b=(b<<1)%mo)
if(a&1)y=(y+b)%mo;
return y;
}
ll f(ll A,ll B,ll C,ll n)
{
if(n==0)return B/C;
if(n<0)return 0;
ll u1=n,u2=n+1;
if(u2%2==0)u2>>=1;else u1>>=1;
ll op=times(u1,u2);
if(A==0)return times(B/C,n+1);
if(A>=C||B>=C)return (times((A/C)%mo,op)+times(B/C,n+1)+f(A%C,B%C,C,n))%mo;
ll m=(A*n+B)/C;
return (times(n,m)-f(C,C-B-1,A,m-1))%mo;
}
int main()
{
cin>>tt;
fo(ttt,1,tt){
cin>>A>>B>>N;
--N; B+=A;
ll a1=B+N*A+B,a2=N+1;
if(a1%2==0)a1>>=1;else a2>>=1;
ll ans=times(a1%mo,a2);
ll k=0,ks=2;
for(;(k=f(A,B,ks,N))!=0;ks<<=1)
ans=(ans-k)%mo;
ans=(ans+mo+mo)%mo;
printf("%lld\n",ans);
}
}