称一个1,2,...,N的排列P1,P2...,Pn是Magic的,当且仅当2<=i<=N时,Pi>Pi/2.
计算1,2,...N的排列中有多少是Magic的,答案可能很大,只能输出模P以后的值
称一个1,2,...,N的排列P1,P2...,Pn是Magic的,当且仅当2<=i<=N时,Pi>Pi/2.
计算1,2,...N的排列中有多少是Magic的,答案可能很大,只能输出模P以后的值
输入文件的第一行包含两个整数 n和p,含义如上所述。
输出文件中仅包含一个整数,表示计算1,2,?, ???的排列中, Magic排列的个数模 p的值。
100%的数据中,1 ≤ ??? N ≤ 106, P??? ≤ 10^9,p是一个质数。 数据有所加强
#include<iostream> #include<algorithm> #include<cstdio> #define MAXN 1000110 using namespace std; int n; long long m,p; long long fact[MAXN],inv[MAXN],val[MAXN],dp[MAXN]; inline int read(){ int date=0,w=1;char c=0; while(c<‘0‘||c>‘9‘){if(c==‘-‘)w=-1;c=getchar();} while(c>=‘0‘&&c<=‘9‘){date=date*10+c-‘0‘;c=getchar();} return date*w; } long long mexp(long long a,long long b,long long c){ long long s=1; while(b){ if(b&1)s=s*a%c; a=a*a%c; b>>=1; } return s%c; } long long lucas(int n,int m,long long p){ if(n<m)return 0; if(m>=p||n>=p)return lucas(n/p,m/p,p)%p*lucas(n%p,m%p,p)%p; return (fact[n]*inv[n-m]%p*inv[m]%p)%p; } void work(){ for(int i=n;i>=1;i--){ val[i]=1; if((i<<1)<=n)val[i]+=val[i<<1]; if((i<<1)+1<=n)val[i]+=val[(i<<1)+1]; if((i<<1)+1<=n)dp[i]=lucas(val[i]-1,val[i<<1],p)%p*dp[i<<1]%p*dp[(i<<1)+1]%p; else if((i<<1)<=n)dp[i]=dp[i<<1]%p; else dp[i]=1; } printf("%lld\n",dp[1]); } void init(){ n=read();p=read(); m=min((long long)n,p-1); fact[0]=1; for(int i=1;i<=m;i++)fact[i]=fact[i-1]*i%p; inv[m]=mexp(fact[m],p-2,p); for(int i=m-1;i>=0;i--)inv[i]=inv[i+1]*(i+1)%p; } int main(){ init(); work(); return 0; }
原文:https://www.cnblogs.com/Yangrui-Blog/p/9482655.html