BZOJ 3209(花神的数论题-数位统计+1,被数据范围坑了)

3209: 花神的数论题

Time Limit: 10 Sec   Memory Limit: 128 MB
Submit: 33   Solved: 18
[ Submit][ Status][ Discuss]

Description

背景
众所周知,花神多年来凭借无边的神力狂虐各大 OJ、OI、CF、TC …… 当然也包括 CH 啦。
描述
话说花神这天又来讲课了。课后照例有超级难的神题啦…… 我等蒟蒻又遭殃了。
花神的题目是这样的
设 sum(i) 表示 i 的二进制表示中 1 的个数。给出一个正整数 N ,花神要问你
派(Sum(i)),也就是 sum(1)—sum(N) 的乘积。

Input

一个正整数 N。

Output

一个数,答案模 10000007 的值。

Sample Input

样例输入一

3

Sample Output

样例输出一

2

HINT



对于样例一,1*1*2=2;


数据范围与约定


对于 100% 的数据,N≤10^15

Source

原创 Memphis

[ Submit][ Status][ Discuss] 

好吧……这题一开始的范围是N<=1015

然后我很天真的以为这不水吗^?结果……

好吧……

之后要来数据以后才发现……

n<=10^15

只有我这种蒟蒻会被这个骗……

BZOJ 3209(花神的数论题-数位统计+1,被数据范围坑了)_第1张图片

被各种D……


Ok,那么这题就是数位统计了……

刚学的……(还在学这个<-弱)

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<functional>
#include<cmath>
#include<cctype>
using namespace std;
#define For(i,n) for(int i=1;i<=n;i++)
#define Rep(i,n) for(int i=0;i<n;i++)
#define Fork(i,k,n) for(int i=k;i<=n;i++)
#define ForD(i,n) for(int i=n;i;i--)
#define Forp(x) for(int p=pre[x];p;p=next[p])
#define RepD(i,n) for(int i=n;i>=0;i--)
#define MAXN (100000)
#define MAXL (50+10)
#define F (10000007)
int a[MAXN],len=0;
long long C[MAXL][MAXL];
long long n;
long long calc(int k)
{
	long long ans=0;
	ForD(i,len)
	{
		if (a[i])
		{
			ans+=C[i-1][k];
			k--;
		}
		if (k<0) return ans;
	}
	return ans;
}
long long pow2(long long a,long long b)
{
	if (b==0) return 1;
	if (b==1) return a;
	long long tmp=pow2(a,b/2);
	tmp=tmp*tmp%F;
	if (b%2) tmp=(tmp*a)%F;
	return tmp;
}
int main()
{
//	freopen("flower1.in","r",stdin);
//	freopen(".out","w",stdout);
	Rep(i,50)
	{
		C[i][0]=1;
		For(j,i) C[i][j]=(C[i-1][j]+C[i-1][j-1]);
	}
	/*
	cout<<pow2(2,1001)<<endl;
	int pp=1;
	For(i,1001) pp=(pp*2)%F;cout<<pp;
	*/
	while (cin>>n)
	{
		n++;//cout<<n<<endl;
		len=0;
		while (n) {a[++len]=n%2;n/=2;}
		long long ans=1;//cout<<len<<endl;
		For(i,len) ans=(ans*pow2(i,calc(i)))%F;
		printf("%lld\n",ans);
	};
	return 0;
}





你可能感兴趣的:(BZOJ 3209(花神的数论题-数位统计+1,被数据范围坑了))