[Luogu P4317] [BZOJ 3209] 花神的數論題
阿新 • • 發佈:2018-12-19
洛谷傳送門
題目背景
眾所周知,花神多年來憑藉無邊的神力狂虐各大 OJ、OI、CF、TC …… 當然也包括 CH 啦。
題目描述
話說花神這天又來講課了。課後照例有超級難的神題啦…… 我等蒟蒻又遭殃了。 花神的題目是這樣的:設 表示 的二進位制表示中 的個數。給出一個正整數 ,花神要問你 ,也就是 的乘積。
輸入輸出格式
輸入格式:
一個正整數 。
輸出格式:
一個數,答案模 的值。
輸入輸出樣例
輸入樣例#1:
3
輸出樣例#1:
2
說明
對於 的資料,
解題分析
數位。 考慮形如這樣的數, 其貢獻為。
於是我們列舉總共出現的次數, 從高往低位考慮。 例如, 我們先考慮中的貢獻, 然後所需的次數減, 考慮的貢獻。 這個過程和SCOI windy數的過程差不多, 都是最後少考慮了的貢獻, 於是先把即可。
組合數預處理的時候對取模, 因為這個WA了三次QAQ…
程式碼如下:
#include <cstdio>
#include <cstring>
#include <cctype>
#include <algorithm>
#include <cmath>
#include <cstdlib>
#define R register
#define IN inline
#define W while
#define gc getchar()
#define MX 65
#define ll long long
#define MOD 10000007
#define PHI 9988440
template <class T>
IN void in(T &x)
{
x = 0; R char c = gc;
for (; !isdigit(c); c = gc);
for (; isdigit(c); c = gc)
x = (x << 1) + (x << 3) + c - 48;
}
IN int fpow(R int base, R int tim)
{
int ret = 1;
W (tim)
{
if (tim & 1) ret = 1ll * ret * base % MOD;
base = 1ll * base * base % MOD, tim >>= 1;
}
return ret;
}
int C[MX][MX], dat[MX];
void pre()
{
for (R int i = 0; i < MX; ++i) C[i][0] = 1;
for (R int i = 1; i < MX; ++i)
for (R int j = 1; j <= i; ++j)
C[i][j] = (C[i - 1][j - 1] + C[i - 1][j]) % PHI;
}
int len, ans = 1;
ll n;
IN int solve(R int need)
{
int ret = 0;
for (R int i = len; i; --i)
{
if(dat[i]) (ret += C[i - 1][need--]) %= PHI;
if(need < 0) break;
}
return ret;
}
int main(void)
{
pre(); scanf("%lld", &n); ++n;
W (n) dat[++len] = n & 1, n >>= 1;
for (R int i = 1; i <= len; ++i) ans = 1ll * ans * fpow(i, solve(i)) % MOD;
printf("%d", ans);
}