8.9题解
最近改题相对顺利,然而考得最烂的一次?自己亲手扔出去60,说个鬼啊当然了,想到不用想,我弃了T3,一会把我昨天欠的dj以及堆优化补完就继续还其他的债了,明天考试,真可怕,但还是要保持微笑呢
T1
是道数学题,废话$le9$的数据,不数学才怪嘞,然而我啥么式子也没搞出来,结果是个玩隔板法的容斥,既然知道隔板法就简单了,不知道的话指路dalao博客,显然随便选的方案用隔板法解决就是$C_{m-1}^{n-1}$,由于隔板法本身就保证了每组中元素个数$\leq1$,所以说我们只要限制上限就可以了,怎么做呢?容斥+隔板,显然最后的答案是随便选-至少一个不满足的+至少两个不满足的-至少三个不满足的$\cdots$,至少$i$个不满足的方案数为$C_{n}^{i}*C_{m-i*k-1}^{n-1}$,这玩意仔细琢磨一下还是可接受的,看一下我看懂之后写的东西吧,我觉得不是特别难接受
然后就阶乘逆元算C就可以了
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #define int long long 5 #define ll long long 6 #define maxn 10000100 7 using namespace std; 8 const long long mod=998244353; 9 int n,m,k; 10 ll ans; 11 ll jc[maxn],ny[maxn]; 12 ll ksm(ll a,ll b,ll c) 13 { 14 ll ans=1; a=a%c; 15 while(b) 16 { 17 if(b&1) ans=(ans*a)%c; 18 a=(a*a)%c; b=b>>1; 19 } 20 return ans%c; 21 } 22 ll C(int n,int m) 23 { 24 if(n<m) return 0; 25 if(n<0) return 0; 26 return ((jc[n]*ny[m])%mod*ny[n-m])%mod; 27 } 28 signed main() 29 { 30 scanf("%lld%lld%lld",&n,&m,&k); 31 if(n>m) {printf("0\n"); return 0;} 32 jc[0]=1; 33 for(int i=1;i<=m;++i) jc[i]=(jc[i-1]*i)%mod; 34 ny[m]=ksm(jc[m],mod-2,mod); 35 for(int i=m;i>=1;--i) ny[i-1]=(ny[i]*i)%mod; 36 ans=C(m-1,n-1); 37 for(int i=1;i<=n;++i) 38 { 39 if(i&1) ans=(ans-(C(n,i)*C(m-i*k-1,n-1))%mod+mod)%mod; 40 else ans=(ans+(C(n,i)*C(m-i*k-1,n-1))%mod)%mod; 41 } 42 printf("%lld\n",ans); 43 return 0; 44 }
T2
其实还是可以想到的,只要读对题,我读对题了,也想到了,就是没打,首先由于它有环,所以我们可以先$tarjan$缩个点,题目的要求是相通的两个点不能同时被炸掉,所以其实就是求最长链的长度,那就缩完点时候,$bfs$或者$dfs$的跑一遍就可以了,注意每个点只搜一遍,不然会T,所以$bfs$可以选用拓扑序,$dfs$可以回溯的时候统计答案,搜的时候如果下面的点被搜到了,直接更新答案然后回溯,不再继续向下搜就可以了
1 #include<iostream> 2 #include<cstdio> 3 #include<stack> 4 #include<vector> 5 #include<cstring> 6 #define maxn 1000100 7 using namespace std; 8 int n,m,js,tot,cnt,j,ans; 9 int head[maxn],to[maxn],xia[maxn]; 10 int dfn[maxn],low[maxn],pd[maxn],ss[maxn]; 11 int h[maxn],t[maxn],x[maxn],du[maxn]; 12 stack <int> s; 13 vector <int> sh[maxn]; 14 void add(int x,int y) 15 { 16 to[++js]=y; xia[js]=head[x]; head[x]=js; 17 } 18 void ADD(int a,int b) 19 { 20 t[++j]=b; x[j]=h[a]; h[a]=j; du[b]++; 21 } 22 void tarjan(int x) 23 { 24 dfn[x]=low[x]=++tot; pd[x]=1; s.push(x); 25 for(int i=head[x];i;i=xia[i]) 26 { 27 int ls=to[i]; 28 if(!dfn[ls]) {tarjan(ls); low[x]=min(low[x],low[ls]);} 29 else if(pd[ls]) low[x]=min(low[x],dfn[ls]); 30 } 31 if(dfn[x]==low[x]) 32 { 33 int y; cnt++; 34 do {y=s.top(); s.pop(); sh[cnt].push_back(y); pd[y]=0; ss[y]=cnt;} 35 while(y!=x); 36 } 37 } 38 void bfs() 39 { 40 while(s.size()) s.pop(); 41 for(int i=1;i<=cnt;++i) 42 if(du[i]==0) {s.push(i); pd[i]=sh[i].size();} 43 while(s.size()) 44 { 45 int ls=s.top(); s.pop(); 46 ans=max(ans,pd[ls]); 47 for(int i=h[ls];i;i=x[i]) 48 { 49 int lss=t[i]; du[lss]--; 50 int js=sh[lss].size(); 51 pd[lss]=max(js+pd[ls],pd[lss]); 52 if(du[lss]==0) {s.push(lss);} 53 ans=max(ans,pd[lss]); 54 } 55 } 56 } 57 int main() 58 { 59 scanf("%d%d",&n,&m); 60 for(int i=1;i<=m;++i) {int u,v; scanf("%d%d",&u,&v); add(u,v);} 61 for(int i=1;i<=n;++i) 62 if(!dfn[i]) tarjan(i); 63 for(int i=1;i<=n;++i) 64 for(int j=head[i];j;j=xia[j]) 65 { 66 int ls=to[j]; 67 if(ss[i]!=ss[ls]) ADD(ss[i],ss[ls]); 68 } 69 memset(pd,0,sizeof(pd)); 70 bfs(); 71 printf("%d\n",ans); 72 return 0; 73 }
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<vector> 5 using namespace std; 6 #define maxn 1001000 7 int read() 8 { 9 register int e=0,f=1; register char ch=getchar(); 10 while(ch<'0'||ch>'9') {if(ch=='-')f=-1; ch=getchar();} 11 while(ch>='0'&&ch<='9') {e=(e<<1)+(e<<3)+(ch^48); ch=getchar();} 12 return e*f; 13 } 14 int n,m,a,b,ma; 15 int js,head[maxn],belong[maxn]; 16 int pd[maxn],deep[maxn],vc[maxn]; 17 struct{ 18 int to,ne; 19 }tree[maxn],tr[maxn]; 20 void qxx(int fr,int tt) 21 { 22 tree[++js].to=tt; 23 tree[js].ne=head[fr]; 24 head[fr]=js; 25 } 26 int head2[maxn]; 27 void qxx2(int fr,int tt) 28 { 29 tr[++js].to=tt; 30 tr[js].ne=head2[fr]; 31 head2[fr]=js; 32 } 33 int tot,num,dfn[maxn],low[maxn],s[maxn],tail,jl[maxn]; 34 vector<int> sc[maxn]; 35 void SCC(int ro) 36 { 37 dfn[ro]=low[ro]=++tot; 38 s[++tail]=ro; jl[ro]=1; 39 for(int i=head[ro];i;i=tree[i].ne) 40 { 41 int son=tree[i].to; 42 if(!dfn[son]) {SCC(son);low[ro]=min(low[ro],low[son]);} 43 else if(jl[son]) low[ro]=min(low[ro],dfn[son]); 44 } 45 if(dfn[ro]==low[ro]) 46 { 47 num++; 48 int tmp; 49 while(1) 50 { 51 tmp=s[tail--]; jl[tmp]=0; 52 sc[num].push_back(tmp); belong[tmp]=num; 53 if(tmp==ro) break; 54 } 55 } 56 } 57 void dfs(int ro) 58 { 59 int qj=0; pd[ro]=1; int sz=sc[ro].size(); 60 for(int i=head2[ro];i;i=tr[i].ne) 61 { 62 int son=tr[i].to; 63 if(deep[son]) {qj=1; deep[ro]=max(deep[ro],deep[son]+sz); continue;} 64 qj=1; 65 dfs(son); 66 deep[ro]=max(deep[ro],deep[son]+sz); 67 } 68 if(!qj) deep[ro]=sz; 69 ma=max(deep[ro],ma); 70 return; 71 } 72 int main() 73 { 74 n=read(); m=read(); 75 for(int i=1;i<=m;++i) 76 { 77 a=read(); b=read(); 78 qxx(a,b); 79 } 80 for(int i=1;i<=n;++i) if(!dfn[i]) SCC(i); 81 //for(int i=1;i<=n;++i) cout<<i<<' '<<belong[i]<<endl; 82 js=0; 83 for(int i=1;i<=n;++i) 84 { 85 int aa=belong[i]; 86 for(int j=head[i];j;j=tree[j].ne) 87 { 88 int son=tree[j].to; int bb=belong[son]; 89 if(aa!=bb) qxx2(aa,bb); 90 } 91 } 92 for(int i=1;i<=n;++i) 93 if(!deep[i]) dfs(i); 94 printf("%d",ma); 95 return 0; 96 }
T3
这个A题率,以及鲜明对比
题解看不懂,不想颓标程,所以留坑,就酱