Processing math: 0%

xjoi Day11 T2题解

众所周知,我的博客园断更很长时间了。。。但是最近突然发现博客园可以用 markdown 然后就回来用一次。
题目链接:点我
30pts做法:
直接暴力一下就好了,n^2 枚举 i,j,然后 O(1) 计算贡献即可。

50pts做法:
使用 cnt[x] 数组表示 1-m 中所有数中,二进制下第 x 位有多少个是 1,那么 \sum_{i=0}^{m} p\ or\ i 就可以直接
p 二进制拆分,然后如果第 k 位是 0,那么这一位对答案的贡献就是这一位 1 的个数,而如果是 1的话
就和 cnt[k] 无关了,而贡献直接就是 m+1,所以 \sum_{i=0}^{m} p\ or\ i 这个式子就很好算了。然后我们枚举
每一个 i,1\leq i\leq n,然后把每一个 i 当成 p ,然后就能 O(n\log n) 做了。

#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
#define ll long long
using namespace std;
const int NR=1e5+10;
const int mod=1e9+7;
int n,m;
ll cnt[50];
ll ans;
int read()
{
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
    return x*f;
}
int main()
{
    n=read(),m=read();
    for(int i=0;i<=m;i++)
    {
        int tot=0,t=i;
	while(t)
	{
	    tot++;
	    cnt[tot]+=(t&1);
	    t>>=1;
	}
    }
    for(int i=0;i<=n;i++)
    {
	int t=i;
	for(int x=1;x<=30;x++)
	{
	    ans+=(t&1)?((1ll*m+1<<x-1)%mod):((1ll*cnt[x]<<x-1)%mod);
	    ans%=mod;
	    t>>=1;
	}
    }
    printf("%lld",ans%mod);
    return 0;
}

100pts做法:
考虑在50pts上优化,我直接对于 n,m 都初始化出来一个 cntcnt[x] 表示第 x 位上有几个 0,分别记为
cnt1,cnt2,然后对于每一位处理,答案就是 n\times m-cnt1[x]times cnt2[x],但是由于 n,m 都是从 0
开始,所以是要把 n++,m++。记住,一定要及时取模,我考试的时候就因为取模问题 100pts->50pts
代码:

#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
#define ll long long
using namespace std;
const int NR=1e5+10;
const int mod=1e9+7;
ll n,m;
ll cnt[NR],cnt2[NR];
ll ans;
ll read()
{
    ll x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
    return x*f;
}
int main()
{
    n=read()+1,m=read()+1;
    for(int i=1;i<=60;i++) cnt[i]=m-(((m>>i)<<i-1)+max(0ll,(m%(1ll<<i)-(1ll<<i-1))));
    for(int i=1;i<=60;i++) cnt2[i]=n-(((n>>i)<<i-1)+max(0ll,(n%(1ll<<i)-(1ll<<i-1))));
    for(int i=1;i<=60;i++) ans+=((n%mod*(m%mod)%mod-cnt[i]%mod*(cnt2[i]%mod)%mod)*((1ll<<i-1)%mod))%mod,ans%=mod;
    printf("%lld",(ans%mod+mod)%mod);
    return 0;
}
posted @   CZD648  阅读(220)  评论(0编辑  收藏  举报
欢迎阅读『xjoi Day11 T2题解』
Live2D
点击右上角即可分享
微信分享提示