您的位置:首页 > 其它

【BZOJ】3209: 花神的数论题

2017-02-16 09:14 316 查看
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=3209

显然是按照二进制位进行DP。

考虑预处理$F[i][j]$表示到了二进制的第$i$位,有$j$个$1$的数字有多少个。

显然:${F[i][j]=F[i-1][j-1]+F[i-1][j]}$

组合数。。。

接下来只需补充不漏的计算比$n+1$小的每一个数字对应的1的多少。数位统计即可。

llg work(llg x)
{
llg tot=0;
for (llg i=tail;i>=1;i--)
{
if (x<0) break;
if (a[i])
{
tot+=c[i-1][x];
x--;
}
}
return tot;
}


View Code
(这上面表示的是有二进制中有$x$个$1$的数有多少个)

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<vector>
#include<cstdlib>
#include<cmath>
#include<cstring>
using namespace std;
#define maxn 10010
#define md 10000007
#define llg long long
#define yyj(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout);
llg n,m,a[maxn],c[100][100],tail,ans;

llg ksm(llg A,llg B)
{
llg ans=1;
while (B)
{
if (B%2) ans*=A,ans%=md;
A*=A; A%=md;
B/=2;
}
return ans;
}

llg work(llg x)
{
llg tot=0;
for (llg i=tail;i>=1;i--)
{
if (x<0) break;
if (a[i])
{
tot+=c[i-1][x];
x--;
}
}
return tot;
}

int main()
{
yyj("bzoj3209");
cin>>n;
n++;
for (llg i=0;i<=60;i++) c[i][0]=1;
for (llg i=1;i<=60;i++)
for (llg j=1;j<=i;j++)
c[i][j]=c[i-1][j]+c[i-1][j-1];
while (n!=0)
{
a[++tail]=n%2;
n/=2;
}
ans=1;
for (llg i=1;i<=60;i++)
ans*=ksm(i,work(i)),ans%=md;
cout<<ans;
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: