zoukankan      html  css  js  c++  java
  • codeforces960G. Bandit Blues

    题目链接:codeforces960G

    来看看三倍经验:hdu4372 luogu4609

    某蒟蒻的关于第一类斯特林数的一点理解QAQ:https://www.cnblogs.com/zhou2003/p/10780832.html

    注意到当前序列的最大值会对前缀最大值和后缀最大值均产生(1)的贡献

    那么当我们去掉这个最大值后,剩下(n-1)个元素,需要产生(a-1)个前缀最大值和(b-1)个后缀最大值,并且它们的位置会以最大值为界限分布在两侧

    我们将剩下的(n-1)个元素分成((a-1)+(b-1))组,每一组钦定最大值在最开头,那么每一个这样的划分就对应了一个合法的序列,最后答案就是(S(n-1,a+b-2)*dbinom{a+b-2}{a-1}),其中(S(n,m))表示第一类斯特林数

    这样你就可以完成后两题了

    那么对于第一题呢?我们有这个式子:

    [S(n,m)=[x^m]prod_{i=0}^{n-1}(x+i) ]

    于是分治+FFT求之,据说有(O(nlogn))的倍增做法?我懒啊

    #include<iostream>
    #include<string.h>
    #include<string>
    #include<stdio.h>
    #include<algorithm>
    #include<math.h>
    #include<vector>
    #include<queue>
    #include<map>
    #include<set>
    using namespace std;
    #define lowbit(x) (x)&(-x)
    #define rep(i,a,b) for (int i=a;i<=b;i++)
    #define per(i,a,b) for (int i=a;i>=b;i--)
    #define maxd 998244353
    typedef long long ll;
    const int N=100000;
    const double pi=acos(-1.0);
    int n,a,b,rev[400400];
    ll s[20][400400];
    
    int read()
    {
    	int x=0,f=1;char ch=getchar();
    	while ((ch<'0') || (ch>'9')) {if (ch=='-') f=-1;ch=getchar();}
    	while ((ch>='0') && (ch<='9')) {x=x*10+(ch-'0');ch=getchar();}
    	return x*f;
    }
    
    ll qpow(ll x,int y)
    {
    	ll ans=1;
    	while (y)
    	{
    		if (y&1) ans=(ans*x)%maxd;
    		x=(x*x)%maxd;
    		y>>=1;
    	}
    	return ans;
    }
    
    ll inv(ll x) {return qpow(x,maxd-2);}
    
    ll C(int n,int m)
    {
    	if (n<m) return 0;
    	ll ans=1;
    	per(i,n,n-m+1) ans=ans*i%maxd;
    	rep(i,1,m) ans=ans*inv(i)%maxd;
    	return ans;
    }
    
    void ntt(int lim,ll *a,int typ)
    {
    	rep(i,0,lim-1)
    		if (i<rev[i]) swap(a[i],a[rev[i]]);
    	int mid;
    	for (mid=1;mid<lim;mid<<=1)
    	{
    		ll wn=qpow(3,(maxd-1)/(mid<<1));
    		int len=(mid<<1),sta,j;
    		if (typ==-1) wn=inv(wn);
    		for (sta=0;sta<lim;sta+=len)
    		{
    			ll w=1;
    			for (j=0;j<mid;j++,w=(w*wn)%maxd)
    			{
    				ll x=a[sta+j],y=a[sta+j+mid]*w%maxd;
    				a[sta+j]=(x+y)%maxd;
    				a[sta+j+mid]=(x+maxd-y)%maxd;
    			}
    		}
    	}
    	if (typ==-1)
    	{
    		int invn=inv(lim);
    		rep(i,0,lim-1) a[i]=a[i]*invn%maxd;
    	}
    }
    
    void solve(int l,int r,int d)
    {
    	if (l==r) {s[d][0]=l;s[d][1]=1;return;}
    	int mid=(l+r)>>1;
    	solve(l,mid,d+1);
    	rep(i,0,mid-l+1) s[d][i]=s[d+1][i];
    	solve(mid+1,r,d+1);
    	int lim=1,cnt=0;
    	while (lim<=(r-l+1)) {lim<<=1;cnt++;}
    	rep(i,mid-l+2,lim) s[d][i]=0;
    	rep(i,r-mid+1,lim) s[d+1][i]=0;
    	rep(i,0,lim-1)
    		rev[i]=(rev[i>>1]>>1)|((i&1)<<(cnt-1));
    	ntt(lim,s[d],1);ntt(lim,s[d+1],1);
    	rep(i,0,lim-1) s[d][i]=s[d][i]*s[d+1][i]%maxd;
    	ntt(lim,s[d],-1);
    }
    
    int main()
    {
    	n=read();a=read();b=read();
    	if ((n-1<a+b-2) || (!a) || (!b)) {printf("0");return 0;}
    	if (n==1) {printf("1");return 0;}
    	solve(0,n-2,0);
    	printf("%lld",C(a+b-2,a-1)*s[0][a+b-2]%maxd);
    	return 0;
    }
    
  • 相关阅读:
    About IL, ILGenerator
    何谓系统架构师(转)
    C# weakreference
    新蛋,您能告诉我,这是怎么了吗?
    C#线程同步的常用关键字简介
    [转]百万级访问网站前期的技术准备
    Gridview控件的使用要点
    Asp.net三种页面传值方法
    浅谈 Vue css scoped & module
    Mac iTerm2 zsh: command not found: node/npm/nvm...
  • 原文地址:https://www.cnblogs.com/encodetalker/p/10780541.html
Copyright © 2011-2022 走看看