LOJ575. "LibreOJ NOI Round # 2" unequal relationship [inclusion and exclusion, divide and conquer FFT]

SIZE

Thinking

It found that there are both greater than less than more difficult task, using the inclusion and exclusion, to be greater than any change of less than minus.

Then finally grow into this string: <<?<?<??<<<?<. We put a contiguous <called a chain. If the number is greater than enumerate what became, the final answer is very easy to count, that is, \ (\ the n-FRAC {!} {\ Prod len!} \) .

\ (dp_i \) representing the forward \ (I \) positions into a number of strands, the number of programs receiving tape repellent coefficients.

\ (dp_i \) from \ (dp_j \) transfer, i.e. \ ([j + 1, i ] \) of these positions with the <connector, and need to meet \ (S_j \) is >. At this time, this >volume into repellency ?, \ ([+ J. 1, I] \) inside the >mess <, can be transferred.

Note \ (cnt_i \) represents \ (S \) before \ (I \) th >number of locations, then there is
\ [dp_i = \ sum_ {j } [s_j \ is \>] dp_j \ times (-1 ) ^ {cnt_ {i-1
} -cnt_ {j}} \ times \ frac {1} {(ji)!} \] partition FFT optimization, no more.

Code

#include<bits/stdc++.h>
clock_t t=clock();
namespace my_std{
    using namespace std;
    #define pii pair<int,int>
    #define fir first
    #define sec second
    #define MP make_pair
    #define rep(i,x,y) for (int i=(x);i<=(y);i++)
    #define drep(i,x,y) for (int i=(x);i>=(y);i--)
    #define go(x) for (int i=head[x];i;i=edge[i].nxt)
    #define templ template<typename T>
    #define sz 401001
    #define mod 998244353ll
    typedef long long ll;
    typedef double db;
    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
    templ inline T rnd(T l,T r) {return uniform_int_distribution<T>(l,r)(rng);}
    templ inline bool chkmax(T &x,T y){return x<y?x=y,1:0;}
    templ inline bool chkmin(T &x,T y){return x>y?x=y,1:0;}
    templ inline void read(T& t)
    {
        t=0;char f=0,ch=getchar();double d=0.1;
        while(ch>'9'||ch<'0') f|=(ch=='-'),ch=getchar();
        while(ch<='9'&&ch>='0') t=t*10+ch-48,ch=getchar();
        if(ch=='.'){ch=getchar();while(ch<='9'&&ch>='0') t+=d*(ch^48),d*=0.1,ch=getchar();}
        t=(f?-t:t);
    }
    template<typename T,typename... Args>inline void read(T& t,Args&... args){read(t); read(args...);}
    char __sr[1<<21],__z[20];int __C=-1,__zz=0;
    inline void Ot(){fwrite(__sr,1,__C+1,stdout),__C=-1;}
    inline void print(register int x)
    {
        if(__C>1<<20)Ot();if(x<0)__sr[++__C]='-',x=-x;
        while(__z[++__zz]=x%10+48,x/=10);
        while(__sr[++__C]=__z[__zz],--__zz);__sr[++__C]='\n';
    }
    void file()
    {
        #ifdef NTFOrz
        freopen("a.in","r",stdin);
        #endif
    }
    inline void chktime()
    {
        #ifndef ONLINE_JUDGE
        cout<<(clock()-t)/1000.0<<'\n';
        #endif
    }
    #ifdef mod
    ll ksm(ll x,int y){ll ret=1;for (;y;y>>=1,x=x*x%mod) if (y&1) ret=ret*x%mod;return ret;}
    ll inv(ll x){return ksm(x,mod-2);}
    #else
    ll ksm(ll x,int y){ll ret=1;for (;y;y>>=1,x=x*x) if (y&1) ret=ret*x;return ret;}
    #endif
//  inline ll mul(ll a,ll b){ll d=(ll)(a*(double)b/mod+0.5);ll ret=a*b-d*mod;if (ret<0) ret+=mod;return ret;}
}
using namespace my_std;

int n;
char s[sz];

ll dp[sz];
int cnt[sz];

ll fac[sz],_fac[sz];
void init(){_fac[0]=fac[0]=1;rep(i,1,sz-1) _fac[i]=inv(fac[i]=fac[i-1]*i%mod);}

int limit,r[sz];
void NTT_init(int n)
{
    limit=1;int l=-1;
    while (limit<=n+n) limit<<=1,++l;
    rep(i,0,limit-1) r[i]=(r[i>>1]>>1)|((i&1)<<l);
}
void NTT(ll *a,int type)
{
    rep(i,0,limit-1) if (i<r[i]) swap(a[i],a[r[i]]);
    for (int mid=1;mid<limit;mid<<=1)
    {
        ll Wn=ksm(3,(mod-1)/mid>>1);if (type==-1) Wn=inv(Wn);
        for (int len=mid<<1,j=0;j<limit;j+=len)
        {
            ll w=1;
            for (int k=0;k<mid;k++,w=w*Wn%mod)
            {
                ll x=a[j+k],y=w*a[j+k+mid]%mod;
                a[j+k]=(x+y)%mod;a[j+k+mid]=(x-y+mod)%mod;
            }
        }
    }
    if (type==1) return;
    ll I=inv(limit);
    rep(i,0,limit-1) a[i]=a[i]*I%mod;
}

ll tmp1[sz],tmp2[sz];
void solve(int l,int r)
{
    if (l==r) { if (l==0) return (void)(dp[l]=1); dp[l]=dp[l]*ksm(mod-1,cnt[l-1]+(l!=n+1?cnt[l]:0))%mod; return; }
    int mid=(l+r)>>1;
    solve(l,mid);
    rep(i,l,mid) if (s[i]!='<') tmp1[i-l]=dp[i];
    rep(i,0,r-l+1) tmp2[i]=_fac[i];
    NTT_init(r-l+1);
    NTT(tmp1,1);NTT(tmp2,1);
    rep(i,0,limit-1) tmp1[i]=tmp1[i]*tmp2[i]%mod;
    NTT(tmp1,-1);
    rep(i,mid+1,r) (dp[i]+=tmp1[i-l])%=mod;
    rep(i,0,limit-1) tmp1[i]=tmp2[i]=0;
    solve(mid+1,r);
}

int main()
{
    file();
    init();
    cin>>(s+1);n=strlen(s+1)+1;
    rep(i,1,n-1) cnt[i]=cnt[i-1]+(s[i]=='>');
    solve(0,n);
    cout<<dp[n]*fac[n]%mod;
    return 0;
}

Guess you like

Origin www.cnblogs.com/p-b-p-b/p/11329111.html