题目描述
我们知道,一个等差数列可以用三个数A,B,NA,B,NA,B,N表示成如下形式:
B+A,B+2∗A,B+3∗A,...,B+N∗AB + A, B + 2 * A, B + 3 * A, ..., B + N * AB+A,B+2∗A,B+3∗A,...,B+N∗A
ztxz16ztxz16ztxz16想知道对于一个给定的等差数列,把其中每一项用二进制表示后,一共有多少位是111。
题目解析
一个类欧几里得的模板。
考虑二进制中第kkk位的贡献
Ansk=∑i=1n[Ai+B的第k位为1]=∑i=1n⌊Ai+b2k⌋−2×⌊Ai+B2k+1⌋Ans_k=\sum_{i=1}^n [Ai+B的第k位为1]=\sum_{i=1}^n\lfloor \frac {Ai+b}{2^k}\rfloor -2\times \lfloor \frac {Ai+B}{2^{k+1}}\rfloorAnsk=i=1∑n[Ai+B的第k位为1]=i=1∑n⌊2kAi+b⌋−2×⌊2k+1Ai+B⌋
然后就是类欧了
Ansk=f(A,A+B,2k,n−1)−2f(A,A+B,2k+1,n−1)Ans_k=f(A,A+B,2^k,n-1)-2f(A,A+B,2^{k+1},n-1)Ansk=f(A,A+B,2k,n−1)−2f(A,A+B,2k+1,n−1)
代码
#include<bits/stdc++.h>
#define ll long long
using namespace std;
ll T,a,b,n,ans;
ll fun(ll n)
{
if(n&1) return (n+1)/2*n;
return n/2*(n+1);
}
ll f(ll a,ll b,ll c,ll n)
{
if(a==0) return (n+1)*(b/c);
if(a<c&&b<c)
{
ll m=(a*n+b)/c;
if(m==0) return 0;
return m*n-f(c,c-b-1,a,m-1);
}
return f(a%c,b%c,c,n)+fun(n)*(a/c)+(n+1)*(b/c);
}
int main()
{
cin>>T;
while(T--)
{
ans=0;
cin>>a>>b>>n;
for(ll i=1;i<=b+a*n;i+=i)
ans+=f(a,b+a,i,n-1)-f(a,b+a,i+i,n-1)*2;
cout<<ans<<endl;
}
}