题目链接:http://www.qscoj.cn/problem/95/
喵哈哈村的秘境探险(四)
发布时间: 2017年4月25日 20:24 最后更新: 2017年4月25日 20:25 时间限制: 1000ms 内存限制: 128M
喵哈哈村的一堆人在前往北京的路上,发现了一个洞穴。由于好奇心大作,于是准备前往洞穴进行探险。
走啊走,喵哈哈村一群人发现了一个先知,这个先知想知道:
设 sum(i) 表示 i 的二进制表示中 1 的个数。给出一个正整数 N ,先知要问你,sum(1)到sum(n)的乘积是多少。
一个正整数 N。
N<=1e15
一个数,答案模 10000007 的值。
复制
8
24
解析:求的是1~n中每个数含1个数的乘积,思路就是合理运用组合数,预先处理好i位选j个1的组合数组c[i][j],然后就是输入一个n,先把它转换成二进制,对于二进制中每一位上的1,咱可以把1后面的所有组合算一下,然后ans再乘以包含此位1的个数,比如说n的二进制为 10000101,计算第一个1,也就是计算1~10000000,然后就是计算10000000~10000100,再然后就是计算10000100~10000101,这样就不会漏掉某个数,ans初始化为1,累乘即可
代码:
#include<bits/stdc++.h>
#define N 109
using namespace std;
typedef long long LL;
const LL mod = 10000007ll;
LL c[69][69];
void init()
{
c[0][0] = c[1][1] = c[1][0] = 1ll;
for(int i = 1; i <= 63; i++)
{
for(int j = 1; j < i; j++)
c[i][j] = c[i-1][j] + c[i-1][j-1];
c[i][0] = c[i][i] = 1;
}
}
LL Pow(LL a, LL b)
{
LL ans = 1ll;
while(b)
{
if(b&1) ans = ans * a % mod;
a = a * a % mod;
b >>= 1;
}
return ans % mod;
}
LL bits[69];
LL solve(LL n)
{
int len = 1;
while(n)
{
if(n&1) bits[len++] = 1;
else bits[len++] = 0;
n >>= 1;
}
// len
LL ans = 1ll; len--;
for(int i = 2; i < len; i++)
{
ans = (ans * Pow(i, c[len-1][i])) % mod;
}
LL k = 1ll;
for(int i = len - 1; i >= 1; i--)
{
if(bits[i])
{
for(int j = 1; j < i; j++)
ans = (ans * Pow(j + k, c[i - 1][j])) % mod;
k++;
ans = ans * k % mod;
}
}
return ans % mod;
}
int main()
{
init();
LL n;
scanf("%lld", &n);
cout << solve(n) << endl;
return 0;
}