zoukankan      html  css  js  c++  java
  • loj#575. 「LibreOJ NOI Round #2」不等关系

    题目描述

    题解

    只想到 $n^2$ 的dp,然后优化不了qwq

    考虑容斥,考虑枚举一下有多少个位置的>是不合法的,其他的>的合法情况是未知的,那对答案的贡献就是 $(-1)^{cnt}$

    然后我们可以dp,设 $f_{i,j}$ 表示前 $i$ 段最多有 $j$ 个上升序列,于是我们列出dp式子 $f_{i,j}=sum_{k=0}^{i-1}f_{k,j-1}(_{s_i-s_k}^{n-s_k})$ ,由于容斥系数是 $±1$ ,所以dp其实没必要即第二维,即 $f_{i}=-sum_{k=0}^{i-1}f_{k}(_{s_i-s_k}^{n-s_k})$ ,然后式子拆开发现可以分治 $Ntt$ ,这里要注意<位置上的dp值设为 $0$ 即可

    效率: $O(nlog^2n)$

    代码

    #include <bits/stdc++.h>
    using namespace std;
    const int N=8e5+5,P=998244353;
    int n,A[N],B[N],t,p,f[N],c,G[2]={3,(P+1)/3},s,re[N],jc[N],ny[N];
    char ch[N];bool a[N];
    int X(int x){if (x>=P) x-=P;return x;}
    void pre(int l){
        for (t=1,p=0;t<l;t<<=1,p++);
        for (int i=0;i<t;i++)
            re[i]=(re[i>>1]>>1)|((i&1)<<(p-1));
    }
    int K(int x,int y){
        int A=1;
        for (;y;y>>=1,x=1ll*x*x%P)
            if (y&1) A=1ll*A*x%P;
        return A;
    }
    void Ntt(int *g,bool o){
        for (int i=0;i<t;i++)
            if (i<re[i]) swap(g[i],g[re[i]]);
        for (int wn,i=1;i<t;i<<=1){
            wn=K(G[o],(P-1)/(i<<1));
            for (int x,y,j=0;j<t;j+=(i<<1))
                for (int w=1,k=0;k<i;k++,w=1ll*w*wn%P)
                    x=g[j+k],y=1ll*w*g[i+j+k]%P,
                    g[j+k]=X(x+y),g[i+j+k]=X(x-y+P);
        }
        if (o)
            for (int i=0,v=K(t,P-2);i<t;i++)
                g[i]=1ll*v*g[i]%P;
    }
    void solve(int l,int r){
        if (l==r){
            if (l==0) f[l]=1;
            else if (!a[l]) f[l]=0;
            else f[l]=1ll*f[l]*(P-ny[n-l])%P;
            return;
        }
        int mid=(l+r)>>1;
        solve(l,mid);
        for (int i=l;i<=mid;i++)
            A[i-l]=1ll*f[i]*jc[n-i]%P;
        for (int i=0;i<=r-l+1;i++) B[i]=ny[i];
        pre(r-l+mid-l+3);Ntt(A,0);Ntt(B,0);
        for (int i=0;i<t;i++)
            A[i]=1ll*A[i]*B[i]%P;Ntt(A,1);
        for (int i=mid+1;i<=r;i++)
            f[i]=X(f[i]+A[i-l]);
        for (int i=0;i<t;i++) A[i]=B[i]=0;
        solve(mid+1,r);
    }
    int main(){
        scanf("%s",ch+1);n=strlen(ch+1)+1;
        for (int i=1;i<n;i++)
            a[i]=(ch[i]=='>'),c+=a[i];
        jc[0]=1;
        for (int i=1;i<=n;i++)
            jc[i]=1ll*i*jc[i-1]%P;
        ny[n]=K(jc[n],P-2);
        for (int i=n;i;i--)
            ny[i-1]=1ll*i*ny[i]%P;
        solve(0,n);
        for (int i=0;i<=n;i++) s=X(s+f[i]);
        if (c&1) s=X(P-s);
        cout<<s<<endl;return 0;
    }
  • 相关阅读:
    领域驱动设计下系统层次结构风格(转载)
    习语
    Dynamic load of a c++ dll in C#?http://www.codecomments.com/archive29020047216328.html
    C#调用DLL文件时参数对应表
    13G编程电子书开始提供BT下载
    如何在C#中加载自己编写的动态链接库(DLL)
    Problem in calling C++ dll from C# Code
    用C++编写的基于双向链表的CPtrArray类
    C++(new and malloc0
    How to create a DLL library in C and then use it with C#
  • 原文地址:https://www.cnblogs.com/xjqxjq/p/12273846.html
Copyright © 2011-2022 走看看