题解 P4317 【花神的数论题】

题目

可能跟某位大佬有点类似,不过我的应该跑得比他快那么一点点......虽然应该没什么关系......


【分析】

假设一个对于一个数 \(N\) ,最高位为第 \(n\)

那么,显然有 \(2^n \leq N \leq 2^{n+1}-1\)

(即第一位一定为 \(1\) ,后面可能 \(1\) ,可能 \(0\))

因此,对于这个数 \(N\) ,我们不能直接拿 \(C_n^m\) 来算

那么我们可以这样考虑,最高位为 \(n\) ,那么,对于后面的 \((n-1)\) 为一定是可 \(1\)\(0\)

因此,假设后面有 \(i\)\(1\) ,故根据排列组合,有 \(C_{n-1}^i\)\(i\),因此它对答案的贡献是 \(i^{C_{n-1}^i}\)

同理,类推出来,\(0\)~\(2^n-1\) 这些数对答案的贡献就是 \(\Pi_{i=1}^{n-1} i^{{C_{n-1}^i}}\)

那么我们现在将第 \(n\) 位固定为 \(1\) ,假设第二个 \(1\) 为第 \(m\)

同样的,它后面的 \((m-1)\) 为一定可 \(1\)\(0\) ,因此同上考虑后 \((m-1)\) 位有 \(i\)\(1\),加上前面那个 \(1\)\((i+1)\)\(i\) ,故贡献为 \((i+1)^{C_{m-1}^i}\)

因此这个 \(1\) 对答案的贡献为 \(\Pi_{i=1}^{m-1} (i+1)^{C_{m-1}^i}\)

如上考虑,每个 \(1\) ,假设是第 \(Cnt\)\(1\),在第 \(Cal\) 位,对答案的贡献就是 \(\Pi_{i=1}^{Cal-1} (i+Cnt)^{C_{Cal-1}^i}\)

把它们都乘起来即可

得到 \((N-1)\) 的答案(LRJ:想一想,为什么?)

所以直接读入的时候 \(N\) 给它 \(+1\) 即可

当然,这边还有一个问题(假装你们都懂得要取模和快速幂):

\(C_{n-1}^i\) 可能会极大无比

这边考虑欧拉公式:\(a^{\varphi(p)} \equiv 1(mod\) \(p)\)

\(\varphi(10000007)=9988440\)

因此,我们在算排列数的时候记得对这个数取模即可

剩下的一些细节就直接看本蒟蒻的代码吧


【代码】

那本蒟蒻就放代码了

#include
using namespace std;
#define f(a,b,c) for(register int a=b;a<=c;a++)
#define g(a,b,c) for(register int a=b;a>=c;a--)
#define Max(a,b) ((a>b)?a:b)
#define Min(a,b) ((a'9')) neg^=!(c^'-'),c=getchar();
    while((c>='0')&(c<='9')) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
    return neg?-ans:ans;
}
ll N,Cnt=0,C[64][64],Ans=1;
int LOG(ll n){ return (n==1)?0:(LOG(n>>1)+1); }
void pre(){
    N=read()+1;
    int n=LOG(N);
    f(i,0,n){
        C[i][i]=C[i][0]=1;
        g(j,i-1,1) C[i][j]=C[i-1][j]+C[i-1][j-1],C[i][j]-=(C[i][j]>=Phi)?Phi:0;
    }
}
int pow(int i,int a){
    if(a==0) return 1; if(a==1) return i;
    ll tmp=pow(i,a>>1);
    tmp=tmp*tmp%Mod*((a&1)?i:1)%Mod;
    return tmp;
}
int main(){
    pre();
    while(N){
        ll Cal=LOG(N);
        if(Cnt) Ans*=Cnt,Ans%=Mod;
        f(i,1,Cal) Ans*=pow(i+Cnt,C[Cal][i]),Ans%=Mod;
        Cnt++;
        N-=(1ll<

最后安利一下 本蒟蒻的博客

你可能感兴趣的:(题解 P4317 【花神的数论题】)