题目
Binary Indexed Tree
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 42 Accepted Submission(s): 7
void add (int x, int t ){
for (int i = x; i != 0; i -= i & (-i))
a[i] += t;
}
If Mr. Frog is required to add t to the interval [l,r], he will add(r,t), and then add(l - 1,-t).
The cost of an interval [l,r] is defined as the number of the “really changed point”. The “really changed point” is the point whose value is modified by the given code.
For example, in order to add 1 to the interval [6,6], Mr. Frog will add 1 to the interval [1,6] (a[6] and a[4] will be added by 1), and add -1 to the interval [1,5] (a[5] and a[4] will be added by -1).
As the result, a[6] will be added by 1, a[5] will be added by -1, and a[4] will be added by 0. a[6] and a[5] are “really changed point”, and the cost is 2.
Mr. Frog wants to calculate the sum of the cost of the interval [l,r]⊆ [1,n] where l and r are two integers. Help Mr. Frog solve the problem.
For each test case, it contains an integer n (1≤n≤1018).
3 1 2 3
Case #1: 1 Case #2: 4 Case #3: 10
大意
分析
代码
#include<cstdio>
#include<cstring>
#define LL __int64
#define mod 1000000007
LL f[70][70],sg[70][70],mi[70],C[70][70];
int dig[70],len;
void init()
{
int i,j,k;
memset(f,0,sizeof(f));
memset(sg,0,sizeof(sg));
memset(mi,0,sizeof(mi));
for(i=0;i<=65;i++)
{
C[0][i]=0;
C[i][0]=1;
}
for(i=1;i<=65;i++)
for(j=1;j<=65;j++)
C[i][j]=(C[i-1][j]+C[i-1][j-1])%mod;
mi[0]=1;
for(i=1;i<=65;i++)
mi[i]=mi[i-1]*2%mod;
f[0][0]=1;
f[1][1]=1;
f[1][0]=1;
for(i=2;i<=65;i++)
{
for(j=0;j<=i;j++)
{
if(j-1>=0)
f[i][j]=(f[i][j]+f[i-1][j-1])%mod;
f[i][j]=(f[i][j]+f[i-1][j])%mod;
}
}
for(i=1;i<=65;i++)
{
sg[i][0]=(sg[i][0]+2*mi[i-1]%mod*mi[i-1]%mod)%mod;
for(k=0;k<i-1;k++)
{
for(j=0;j<=k+1;j++)
{
sg[i][j]=(sg[i][j]+C[k+1][j]*2%mod*mi[i-k-2]%mod*mi[i-k-2]%mod)%mod;
}
}
}
}
LL cal1(LL n)
{
LL ans=0;
int i,j;
int cnt1=0;
for(i=len-1;i>=0;i--)
{
if(dig[i]==0)
continue;
for(j=i;j>=0;j--)
ans=(ans+f[i][j]*(j+cnt1)%mod)%mod;
cnt1++;
}
ans=(ans+cnt1)%mod;
n%=mod;
ans=ans*n%mod;
return ans;
}
LL cal2(LL n)
{
LL ans=0;
int i,j,k;
int cnt1=0;
for(i=len-1;i>=0;i--)
{
if(dig[i]==0)
continue;
n-=((LL)1<<i);
ans=(ans+(n+1)%mod*mi[i]%mod*cnt1*2%mod)%mod;
for(k=0;k<i;k++)
{
ans=(ans+sg[i][k]*(k+cnt1)%mod)%mod;
}
cnt1++;
}
return ans;
}
int main()
{
LL n;
int t,cas=1;
scanf("%d",&t);
init();
while(t--)
{
scanf("%I64d",&n);
len=0;
LL tmp=n;
while(tmp)
{
dig[len++]=tmp%2;
tmp/=2;
}
LL ans=cal1(n);
printf("Case #%d: %I64d\n",cas++,(ans-cal2(n)+mod)%mod);
}
return 0;
}
6873



被折叠的 条评论
为什么被折叠?



