[HNOI2009]有趣的数列(杨氏矩阵+钩子公式)

https://www.luogu.com.cn/problem/P3200

这就是一个2行n列的杨氏矩阵,直接利用钩子公式求解

注意阶乘的质因子分解
单个数质因子分解枚举到根号

#include<cstdio>
#include<cmath>
#include<algorithm>

using namespace std;

#define N 2000001

int mod;

int p[N],v[N],cnt; 
int tot[N];

void prep()
{
    for(int i=2;i<N;i++)
    {
        if(!v[i])  p[++cnt]=i;
        for(int j=1;j<=cnt;j++)
        {
            if(p[j]*i>=N) break;
            v[p[j]*i]=true;
            if(i%p[j]==0) break;
        }
    }
}

void divide(int x,int y)
{
	int xx=sqrt(x);
	for(int i=1;i<=cnt && p[i]<=xx;++i)
		while(!(x%p[i]))
		{
			x/=p[i];
			tot[i]+=y;
		}
	if(x>1) tot[lower_bound(p+1,p+cnt+1,x)-p]+=y; 
}

int pow(int a,int b)
{
    int c=1;
    for(;b;b>>=1,a=a*a%mod)
    	if(b&1) c=c*a%mod;
    return c;
}

int main()
{
	prep();
	int n,t,m;
	scanf("%d%d",&n,&mod);
	t=n*2;
	for(int i=1;i<=cnt && p[i]<=t;++i)
	{
		m=t;
		while(m)
		{
			tot[i]+=m/p[i];
			m/=p[i];
		}
	}
	for(int j=2;j<=n;++j)
		divide(1+n-j+1,-2); 
	divide(n+1,-1);
	long long ans=1;
	for(int i=1;i<=cnt;++i) 
		ans=ans*pow(p[i],tot[i])%mod;
	printf("%lld",ans);
}
posted @ 2021-05-10 18:38  TRTTG  阅读(120)  评论(0编辑  收藏  举报