zoukankan      html  css  js  c++  java
  • 有趣的数列 唯一分解定理+卡特兰数

    问题:
    我们称一个长度为(2n)的数列是有趣的,当且仅当该数列满足以下三个条件:

    (1)它是从(1)(2n)(2n)个整数的一个排列{(Ai)};

    (2)所有的奇数项满足(A1<A3<…<A2n-1),所有的偶数项满足(A2<A4<…<A2n)

    (3)任意相邻的两项(A2i-1)(A2i(1≤i≤n))满足奇数项小于偶数项,即:(A2i-1<A2i)

    现在的任务是:对于给定的(n),请求出有多少个不同的长度为(2n)的有趣的数列。因为最后的答案可能很大,所以只要求输出答案(mod P)的值。

    解:
    $1 2 5 14 42 $
    奇数小于偶数 (入栈>=出栈) 这是一个卡特兰数

    我们应该用 一下公式求解
    $ frac {c_{2n}^n}{n+1}$ =(frac {2n!} {n!*n!})*(frac {1} {n+1})=(prod_{n+2}^{2**n})

    但是这道题还是没有完
    你会发现它模数不一定是质数 所以你要用扩展lucas

    好吧其实是唯一分解定理来进行约分

    虽然我不知道为什么 可以约分
    开先我对于每个质因数筛次数 (T 50)
    经过hyh 的指点
    我才发现 可以从后往前讨论 对每个数进行分解 (sqrt)级别

    code:

    #include<stdio.h>
    #include<iostream>
    using namespace std;
    #define maxnn 2000100
    #define ll long long
    ll zhi[maxnn];
    ll n,p;
    ll phi[maxnn];
    ll cnt[maxnn];
    ll len=0;
    ll is[maxnn];
    void init()
    {
        phi[1]=1;
        for(ll i=2;i<=2000000;i++)
        {
            if(!phi[i])
                zhi[++len]=i;
            for(int j=1;j<=len&&zhi[j]*i<=2000000;j++)
            {
                phi[zhi[j]*i]=1;
                if(i%zhi[j]==0) break;
            }
        }
    }
    void iiit(){
      
        for(ll i=2*n;i>=1;i--)
        {
            if(is[i])
        {
            if(zhi[lower_bound(zhi+1,zhi+len+1,i)-zhi]==i) continue;
            for(int j=2;j*j<=i;j++)
            {
                if(i%j==0)
                {
                    is[j]+=is[i];
                    is[i/j]+=is[i];
                    break;
                }
            }
        }
        }
        for(int i=1;i<=len&&zhi[i]<=2*n;i++)
        {
            if(is[zhi[i]]) cnt[zhi[i]]+=is[zhi[i]];
        }
    }
    ll ksm(ll a,ll b)
    {
        ll ans=1;
        while(b)
        {
            if(b&1) ans=ans*a%p;
            a=a*a%p;
            b>>=1;
        }
        return ans;
    }
    int main(){
        cin>>n>>p;
        for(ll i=n+2;i<=2*n;i++) is[i]=1;
        for(ll i=1;i<=n;i++) is[i]=-1;
        init();
        iiit();
        ll tot=1;
        for(ll i=1;i<=len&&zhi[i]<=2*n;i++)
        {
            if(cnt[zhi[i]]) tot=tot*ksm(zhi[i],cnt[zhi[i]])%p;
        }
        cout<<tot%p;
    }
    
    刀剑映出了战士的心。而我的心,漆黑且残破
  • 相关阅读:
    oracle基本语句
    html页面比较长,如何用js实现网页一打开显示在网页的中部?
    idea拉出Output窗口和还原窗口
    关于idea的目录结构如何变成树状,也就是横向变纵向
    IDEA -- idea无法导入HttpServlet包解决方法
    tomcat启动startup.bat一闪而过
    li标签和checkbox绑定
    利用jQuery对li标签操作
    &#65279导致页面顶部空白一行解决方法
    Myeclipse快速排版的快捷键
  • 原文地址:https://www.cnblogs.com/OIEREDSION/p/11495105.html
Copyright © 2011-2022 走看看