标签:namespace 分享 stdin 状态 ros else microsoft es2017 ios
T1
f(i)表示不和法数大于i个的数量
$$f(i)=C_n^iC_{m-i*k-1}^{n-1}$$
首先n>m||K*n<m一定不合法
先不考虑<K的情况,那就相当于给m个果子,用n个篮子把他们装起来
用挡板法易知
$$ans=C_{m+n-1}^{n-1}$$
即给m个果子中间再加上n-1个挡板的位置,在选n-1个
那考虑必须放一个的情况,只要预先把m -n,相当于每个篮子先放一个
那考虑不合法数>=i个,只需要预先给i个放K个,那这i个一定不合法
但是不保证其他的合法,也不保证这i个不合法的果子数一定是K+1个
所以要用到容斥
这种我们确定了i个不合法的最低高度,但是同一个状态会被像上图一样,被枚举多次
所以要容斥
#include <cstdio> #include <cstring> #include <cstdlib> #include <iostream> #include <cmath> #include <algorithm> #define mem(a,b) memset(a,b,sizeof(a)) #define ll long long using namespace std; const int mod=998244353; const int N=10000066; ll mi(ll a,ll ci) { ll ans=1; while(ci) { if(ci&1) ans=ans*a%mod; a=a*a%mod; ci>>=1; } return ans; } ll jie[N],jieni[N]; void chu() { jie[0]=1; for(int i=1;i<N;++i) jie[i]=jie[i-1]*i%mod; jieni[N-1]=mi(jie[N-1],mod-2)%mod; for(int i=N-2;i>=1;--i) jieni[i]=jieni[i+1]*(ll)(i+1)%mod; jieni[0]=1; } ll n,m,K; inline ll C(ll n,ll m) { if(n<0||m<0) return 0; if(n<m) return 0; return jie[n]*jieni[m]%mod*jieni[n-m]%mod; } int main(){ //freopen("T1.in","r",stdin); chu(); scanf("%lld%lld%lld",&n,&m,&K); if(n>m) { cout<<0; return 0; } ll ans=0; for(ll i=0;i<=m;++i) ans=(ans+C(n,i)*C(m-i*K-1,n-1)%mod*((i&1)?-1:1)+mod)%mod; cout<<ans%mod; }
T2
仔细想一想就会发现
一条链上、一个环上只能放一个
如果有多条链、多个环组合在一起,ans还是最长链的长度
那只需要tarjan缩个点,再求个最长链即可
#include <cstdio> #include <cstring> #include <cstdlib> #include <iostream> #include <cmath> #include <algorithm> #define mem(a,b) memset(a,b,sizeof(a)) #define ll long long #define dd double using namespace std; inline int read() { char q=getchar();int ans=0; while(q<‘0‘||q>‘9‘)q=getchar(); while(q>=‘0‘&&q<=‘9‘){ans=ans*10+q-‘0‘;q=getchar();} return ans; } const int N=1000006; struct son { int v,next; }; struct TTT { son a1[N*3]; int first[N*3],e; void clear() { mem(a1,0);mem(first,-1);e=0; } void addbian(int u,int v) { a1[e].v=v; a1[e].next=first[u]; first[u]=e++; } }h[2]; int n,m; int dfn[N],low[N],now; int zhan[N*5],he; bool flag[N]; int dui[N],con,sun[N]; inline void tarjan(int x) { low[x]=dfn[x]=++now; zhan[++he]=x;flag[x]=1; int temp; for(int i=h[0].first[x];i!=-1;i=h[0].a1[i].next) { temp=h[0].a1[i].v; //if(flag[temp]) // continue; if(dfn[temp]==-1) { tarjan(temp); if(low[x]>low[temp]) low[x]=low[temp]; //low[x]=min(low[x],low[temp]); } else if(flag[temp]) { if(low[x]>dfn[temp]) low[x]=dfn[temp]; //low[x]=min(low[x],dfn[temp]); } } if(dfn[x]==low[x]) { ++con; while(1) { temp=zhan[he--]; flag[temp]=0; dui[temp]=con; ++sun[con]; if(temp==x) break; } } } void chu() { for(int i=1;i<=n;++i) if(dfn[i]==-1) tarjan(i); for(int i=1;i<=n;++i) { int temp; for(int j=h[0].first[i];j!=-1;j=h[0].a1[j].next) { temp=h[0].a1[j].v; if(dui[i]!=dui[temp]) h[1].addbian(dui[i],dui[temp]); } } } int mx[N]; void dfs(int x) { flag[x]=1; int temp; mx[x]=sun[x]; for(int i=h[1].first[x];i!=-1;i=h[1].a1[i].next) { temp=h[1].a1[i].v; if(flag[temp]) { if(mx[x]<sun[x]+mx[temp]) mx[x]=sun[x]+mx[temp]; continue; } dfs(temp); if(mx[x]<sun[x]+mx[temp]) mx[x]=sun[x]+mx[temp]; } } int work() { mem(flag,0); for(int i=1;i<=con;++i) if(!flag[i]) dfs(i); int ans=0; for(int i=1;i<=con;++i) if(ans<mx[i]) ans=mx[i]; return ans; } int main(){ //freopen("T2.in","r",stdin); //freopen("bomb.in","r",stdin); mem(dfn,-1); h[0].clear(); h[1].clear(); n=read();m=read(); int tin1,tin2; for(int i=1;i<=m;++i) { tin1=read();tin2=read(); h[0].addbian(tin1,tin2); } chu(); /*printf("\n"); for(int i=1;i<=n;++i) printf("%d ",dui[i]); printf("\n");*/ cout<<work(); }
然后T3还不会呢...
标签:namespace 分享 stdin 状态 ros else microsoft es2017 ios
原文地址:http://www.cnblogs.com/A-LEAF/p/7643811.html