[BZOJ 3209] 花神的数论题 【数位统计】

题目链接: BZOJ - 3209

 

题目大意

设 f(x) 为 x 的二进制表示中 1 的个数。给定 n ,求 ∏ f(i)     (1 <= i <= n) 。

 

题目分析

总体思路是枚举每一个 t ,算出 f(x) = t 的 x 有 y 个,然后将 t^y 算入答案中。

主要的过程是求 y ,也就是代码中的 Solve(t) 。

详见代码吧,我只能看别人的题解,自己想不出来QAQ

 

注意:WA警告!WA警告!

Warning!Warning!Warning!

在涉及到计算 a^b%p 的计算中,a 可以先 mod p ,但是 b 不可以!!!计算 b 的时候,因为 b 之后要作为指数,所以绝对不能取模!!!!!

在这道题中,组合数不能取模!!!Solve() 不能取模!!!因为这些都与指数有关!! 

 

代码

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>

using namespace std;

typedef long long LL;

const int MaxL = 60 + 5;
const LL Mod = 10000007;

LL n, Ans;
LL C[MaxL][MaxL];
int l, Bit[MaxL];

void Init_C() {
	for (int i = 0; i <= 60; ++i) {
		C[i][0] = 1;
		for (int j = 1; j <= i; ++j) 
			C[i][j] = C[i - 1][j - 1] + C[i - 1][j];
	}
}

LL Solve(int x) {
	LL ret = 0;
	for (int i = l; i >= 1; --i) {
		if (Bit[i] == 1) {
			ret += C[i - 1][x];
			--x;
		}
		if (x < 0) break;
	}
	return ret;
}

LL Pow(LL a, LL b) {
	LL ret = 1, f = a % Mod;
	while (b) {
		if (b & 1) {
			ret *= f;
			ret %= Mod;
		}
		b >>= 1;
		f *= f;
		f %= Mod;
	}
	return ret;
}

int main() 
{
	Init_C();
	while (scanf("%lld", &n) != EOF) {
		++n;
		l = 0;
		while (n) {
			Bit[++l] = n & 1;
			n >>= 1;
		}
		Ans = 1ll;
		for (int i = 1; i <= l; ++i)
			Ans = Ans * Pow(i, Solve(i)) % Mod;
		printf("%lld\n", Ans);
	}
	return 0;
}

  

posted @ 2015-01-19 17:12  JoeFan  阅读(257)  评论(0编辑  收藏  举报