洛谷 P4317 花神的数论题


题目:

传送门


题意:

给出一个正整数 n n n ,问你 ∏ i = 1 N s u m ( i ) \prod_{i=1}^{N}sum(i) i=1Nsum(i)
p . s . s u m ( i ) p.s. sum(i) p.s.sum(i) i i i在二进制下时 1 1 1的个数


分析:

对于数 n n n来说,必定是 1 — n 1—n 1n中最大的这不废话吗
因此,可以有两个引理:
1. 1. 1.在二进制下 t a ta ta的首位 1 1 1一定是出现最早的
2. 2. 2.首位 1 1 1出现的位置后都必定存在 1 1 1
证明:
1. 1. 1.因为 n n n是最大的,所以显然(逃
2. 2. 2.假设 n n n 4 4 4,,则在二进制下为 1000 1000 1000,因为我们要求的是 1 — n 1—n 1n。所以必定存在一个恰好比 n n n少一位并且所有位上的都是 1 1 1,我们成为 s u p e r super super n u m b e r number number。在这个例子中, s u p e r   n u m b e r super\ number super number 3 3 3,即 111 111 111
根据 引 理 1 引理1 1,我们得到了需要倒序求解的思路
( n 2 表 示 (n_2表示 (n2n 的 二 进 制 数 ) 的二进制数) )
根据 引 理 2 引理2 2,我们知道的当 n 2 n_2 n2出现 1 1 1后,之后便可以直接累加
用人话来说,设 f i f_i fi 1 1 1出现次数恰好为 i i i时的方案数(雾不知道怎么正确表达)
随后我们可以得到一个式子:
∑ i = n 1 f [ i ] + = f [ i − 1 ] ( 其 实 不 需 要 ∑ , 只 是 觉 得 这 样 表 示 循 环 比 较 高 级 233 ) \sum_{i=n}^1f[i]+=f[i-1](其实不需要\sum,只是觉得这样表示循环比较高级233) i=n1f[i]+=f[i1](233)
也就是上文说到的累加,当我们遍历多一位时, 1 1 1出现的次数便必然会 + 1 +1 +1
P . S . P.S. P.S.因为我们不能保证 n n n一定是 s u p e r   n u m b e r super\ number super number,所以统计 1 1 1出现的次数时从 0 0 0开始统计,最后再补上一次便不会漏记,且因为我们补得是最后一位,所以不用再进行累加


代码:

// luogu-judger-enable-o2
#include<cstdio>
#include<string>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<queue>
#define LL long long 
#define LZX 10000007
inline LL read() {
    LL d=0,f=1;char s=getchar();
    while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
    while(s>='0'&&s<='9'){d=d*10+s-'0';s=getchar();}
    return d*f;
}
using namespace std;
LL ksm(LL x,LL y)
{
    LL s=1;
    while(y)
    {
        if(y%2) (s*=x)%=LZX;
        y/=2;(x*=x)%=LZX;
    }
    return s;
}
LL f[55],cnt=0;
int main()
{
    LL n=read();
    for(LL j=49;~j;j--)
    { 
        for(LL i=49;i;i--) f[i]+=f[i-1];
        if(n>>j&1) f[cnt++]++;
    }
    f[cnt]++;
    LL ans=1;
    for(LL i=1;i<=49;i++)
      (ans*=ksm(i,f[i]))%=LZX;
    cout<<ans;	  
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值