8.9 NOIP模拟测试15 建设城市(city)+轰炸行动(bomb)+石头剪刀布(rps)
时间:2019-08-09
本文章向大家介绍8.9 NOIP模拟测试15 建设城市(city)+轰炸行动(bomb)+石头剪刀布(rps),主要包括8.9 NOIP模拟测试15 建设城市(city)+轰炸行动(bomb)+石头剪刀布(rps)使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
鉴于T3的惨烈程度,我决定先来颓篇题解。
T1 建设城市(city)
挡板法+容斥
m个建设队分成n组,每组必须有一个,先不考虑上限,共有 C(m-1,n-1)种方案。
有i个组是超过k个的,容斥掉 C(n,i)*C(m-i*k-1,n-1) 相当于把i×k个建设队拿出来,把剩下的m-i*k个建设队分成n组并且保证每个组都至少有一个且不考虑上界,再把这i个k放进n个分组里,就至少有i个组是大于k的。
#include<iostream> #include<cstring> #include<cstdio> #define mod 998244353 #define ll long long using namespace std; ll n,m,k,fac[10001000],inv[10001000],facinv[10001000],ans; ll C(ll x,ll y) { if(y>x) return 0; return fac[x]*facinv[y]%mod*facinv[x-y]%mod; } int main() { scanf("%lld%lld%lld",&n,&m,&k); if(n>m){ puts("0"); return 0; } fac[0]=1;facinv[0]=1;inv[1]=1; for(int i=1;i<=max(n,m);i++){ if(i!=1) inv[i]=(mod-mod/i)*inv[mod%i]%mod; fac[i]=fac[i-1]*i%mod; facinv[i]=facinv[i-1]*inv[i]%mod; } for(int i=1;i<=n;i++){ if(i&1) ans=(ans+C(n,i)*C(m-i*k-1,n-1))%mod; else ans=(ans-C(n,i)*C(m-i*k-1,n-1)+mod)%mod; } printf("%lld\n",(C(m-1,n-1)-ans+mod)%mod); return 0; }
T2 轰炸行动(bomb)
考场好多看错题的,但是我没看错也没做出来(就是个废物)
移动是只要是有路径能到达就可以,那么我们tarjan缩点,缩完点后建新图,找最长链,每个点的深度应是父节点深度+点的size(几个点缩在一起),topu或dfs求最长链(但dfs好像容易T)。
#include<iostream> #include<cstdio> #include<queue> using namespace std; struct node { int to,nxt; }h[4001000],hh[4001000]; int n,m,nxt[4001000],tot,tet,cnt,dfn[1001000],low[1001000],s[1001000]; int top,num,whos[1001000],sz[1001000],du[1001000],dep[1001000],ans,nx[4001000]; bool is[1001000]; int max(int x,int y) { return x>y?x:y; } void add(int x,int y) { h[++tot].to=y; h[tot].nxt=nxt[x]; nxt[x]=tot; } void ad(int x,int y) { hh[++tet].to=y; hh[tet].nxt=nx[x]; nx[x]=tet; } void tarjan(int x) { dfn[x]=low[x]=++cnt; s[++top]=x;is[x]=1; for(int i=nxt[x];i;i=h[i].nxt){ int y=h[i].to; if(!dfn[y]){ tarjan(y); low[x]=min(low[x],low[y]); } else if(is[y]) low[x]=min(low[x],dfn[y]); } if(dfn[x]==low[x]){ num++; while(1){ int tmp=s[top--]; is[tmp]=0; whos[tmp]=num; sz[num]++; if(x==tmp) break; } } } void topu() { queue<int>q; for(int i=1;i<=num;i++) if(du[i]==0) q.push(i),dep[i]=sz[i],ans=max(ans,dep[i]); while(q.size()){ int x=q.front();q.pop(); for(int i=nx[x];i;i=hh[i].nxt){ int y=hh[i].to; du[y]--; dep[y]=max(dep[y],dep[x]+sz[y]); ans=max(ans,dep[y]); if(!du[y]) q.push(y); } } } int main() { scanf("%d%d",&n,&m); int u,v; for(int i=1;i<=m;i++){ scanf("%d%d",&u,&v); add(u,v); } for(int i=1;i<=n;i++) if(!dfn[i]) tarjan(i); for(int i=1;i<=n;i++){ for(int j=nxt[i];j;j=h[j].nxt){ int y=h[j].to; if(whos[i]!=whos[y]){ ad(whos[i],whos[y]); du[whos[y]]++; } } } topu(); printf("%d\n",ans); }
原文地址:https://www.cnblogs.com/jrf123/p/11328044.html
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法