【洛谷P4317】花神的数论题

题目

题目链接:https://www.luogu.com.cn/problem/P4317
话说花神这天又来讲课了。课后照例有超级难的神题啦…… 我等蒟蒻又遭殃了。 花神的题目是这样的:设 \(\text{sum}(i)\) 表示 \(i\) 的二进制表示中 \(1\) 的个数。给出一个正整数 \(N\) ,花神要问你 \(\prod_{i=1}^{N}\text{sum}(i)\) ,也就是 \(\text{sum}(1)\sim\text{sum}(N)\) 的乘积。

思路

\(f(i)\) 为有 \(i\) 个一的方案数。可以用组合数乱搞搞出。
答案即为

\[\Pi^{\log n}_{i=1} i^{f(i)} \]

时间复杂度 \(O(\log^2 n)\)

代码

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

const int MOD=10000007,LG=55;
ll n,cnt,ans,f[LG+1],C[LG+1][LG+1];

ll fpow(ll x,ll k)
{
	ll ans=1;
	for (;k;k>>=1,x=x*x%MOD)
		if (k&1) ans=ans*x%MOD;
	return ans;
}

int main()
{
	C[1][0]=C[1][1]=1;
	for (int i=2;i<=LG;i++)
		for (int j=0;j<=i;j++)
			C[i][j]=C[i-1][j]+C[i-1][j-1];
	scanf("%lld",&n);
	for (int i=LG;i>=0;i--)
		if (n&(1LL<<i))
		{
			for (int j=1;j<=i;j++) f[j+cnt]+=C[i][j];
			cnt++; f[cnt]++;
		}
	ans=1;
	for (int i=1;i<=LG;i++)
		ans=ans*fpow(i,f[i])%MOD;
	printf("%lld",ans);
	return 0;
}
原文地址:https://www.cnblogs.com/stoorz/p/13786114.html