2017/10/15模拟赛总结
来源:互联网 发布:qt mysql数据库 编辑:程序博客网 时间:2024/06/05 03:16
题目来自计蒜客2017 NOIP 提高组模拟赛(四)Day2
T1 鬼脚图
不难发现一条横线的效果是把
所以对于第一个问题直接按顺序交换一遍即可
这样第二个问题就转化为使一个排列两两相邻交换变成升序的最少交换次数
这也就是逆序对的个数 用归并排序或BIT求一下即可
#include<bits/stdc++.h>using namespace std;#define N 100010#define M 1000010void rd(int &x){ char c;x=0; while (c=getchar(),c<48); do x=(x<<1)+(x<<3)+(c^48); while (c=getchar(),c>=48);}int n,m,ans[N];struct Binary_Indexed_tree{ int bit[N]; void add(int i){ while (i){ bit[i]++; i-=i&-i; } } int query(int i){ int res=0; while (i<=n){ res+=bit[i]; i+=i&-i; } return res; }}BIT;int main(){ int i; rd(n),rd(m); for (i=1;i<=n;i++) ans[i]=i; for (i=1;i<=m;i++){ int x; rd(x); swap(ans[x],ans[x+1]); } for (i=1;i<=n;i++) printf("%d ",ans[i]); long long sum=0; for (i=1;i<=n;i++){ sum+=BIT.query(ans[i]); BIT.add(ans[i]); } printf("\n%lld\n",sum); return 0;}
T2 跑步爱天天
首先不难发现警卫的路径是互相包含的 祖先包含儿子的路径
那么可以预处理出1节点的路径 然后每个点顺便求出在路径上循环开始和结束的位置
这样可以每次模拟每个警卫走一步 而总共要跳
考虑链的情况
只需要考虑起点的祖先中距离为偶数的
因为奇数距离会导致穿过之后无法再追上 肯定不会相遇
注意有可能不是以1为端点 (虽然数据都是1为端点)
其实有了前面考虑的几个条件 就离正解不远了
先把所有起点的祖先在路径上第一次出现的位置mark掉
可以枚举相遇的点的在路径上每个对应的位置
然后判断在路径数组里向前走同样步数有没有祖先
一个点的多个对应的位置 可以用一个链表存
#include<bits/stdc++.h>using namespace std;#define N 500010void rd(int &x){ char c;x=0; while (c=getchar(),c<48); do x=(x<<1)+(x<<3)+(c^48); while (c=getchar(),c>=48);}struct edge{ int nxt,t;}e[N];int head[N],edge_cnt,n,S,a[N];void add_edge(int x,int y){ e[edge_cnt]=(edge){head[x],y}; head[x]=edge_cnt++;}int fa[N],id[N],dfs_cnt,nxt[N<<1];bool mark[N<<1];void dfs(int x,int f){ id[x]=++dfs_cnt; fa[x]=f; int i,las=id[x]; for (i=head[x];~i;i=e[i].nxt){ int to=e[i].t; dfs(to,x); nxt[las]=++dfs_cnt; las=dfs_cnt; } nxt[las]=-1;}int main(){ int Case,i,j; rd(Case); while (Case--){ memset(head,-1,sizeof(head)); memset(mark,0,sizeof(mark)); dfs_cnt=edge_cnt=0; rd(n); for (i=1;i<=n;i++){ int x; rd(x); for (j=1;j<=x;j++) rd(a[j]); for (j=x;j;j--) add_edge(i,a[j]); } rd(S); dfs(1,0); int x=S,ans=0; while (x){ mark[id[x]]=1; x=fa[x]; } x=S; int stp=0,i; while (x){ for (i=id[x];~i;i=nxt[i]){ if (i-stp<=0) continue; ans+=mark[i-stp]; mark[i-stp]=0; } x=fa[x]; stp++; } printf("%d\n",ans); } return 0;}
T3 神奇的三角形
找规律可以发现
然后对于
再看
再找规律可以发现 分别是
但是对于再大一点的
考虑上面那个式子的组合意义
即对于所有的
但是这样难以直接求解
换一种思路:先枚举一种情况里实际用了
再乘上i种颜色的方案数
这样包含了只取比
最后方案数为
对于正解要用
留着以后填坑吧
#include<bits/stdc++.h>using namespace std;#define mo 998244353int Pow(int a,int b){ int res=1; while (b){ if (b&1) res=1LL*res*a%mo; b>>=1; a=1LL*a*a%mo; } return res;}int n,m;struct P1{ int sum[1000010]; void solve(){ int i,ans=0; sum[0]=1; for (i=1;i<=n/2+1;i++){ sum[i]=1LL*sum[i-1]*(n+1-i)%mo*Pow(i,mo-2)%mo; ans=(ans+1LL*sum[i]*Pow(i,m))%mo; } for (;i<=n;i++) ans=(ans+1LL*sum[n-i]*Pow(i,m))%mo; printf("%d\n",ans); }}P40;struct P5{ int A[3010],Inv[3010]; void solve(){ int i,j,ans=0; for (i=1;i<=3000;i++) A[i]=Pow(i,m),Inv[i]=Pow(i,mo-2); int C=1,Pow2=Pow(2,n); for (i=1;i<=m;i++){ C=1LL*C*(n+1-i)%mo*Inv[i]%mo; Pow2=1LL*Pow2*Inv[2]%mo; int sum=1LL*C*Pow2%mo,cnt=A[i]; int f=-1,C1=1; for (j=i-1;j;j--){ C1=1LL*C1*Inv[i-j]%mo*(j+1)%mo; cnt=(cnt+1LL*f*C1*A[j])%mo; f=-f; } ans=(ans+1LL*sum*cnt)%mo; } printf("%d\n",(ans+mo)%mo); }}P95;int main(){ scanf("%d%d",&n,&m); if (n<=1000000) P40.solve(); else if (m<=3000) P95.solve(); return 0;}
Date:2017/10/16
By CalvinJin
- 2017/10/15模拟赛总结
- 2017/10/10模拟赛总结
- 2017/10/7模拟赛总结
- 2017/10/9模拟赛总结
- 2017/10/6模拟赛总结
- 2017/10/12模拟赛总结
- 2017/10/16模拟赛总结
- 2017/10/21模拟赛总结
- 2017/10/23模拟赛总结
- 2017/10/25模拟赛总结
- 2017/10/30模拟赛总结
- 2017.4.15模拟赛总结
- NOIP2017模拟赛(10) 总结
- 10-15&&10-16NOIP模拟赛总结
- 2016.4.15省选模拟赛总结
- jzoj 模拟赛总结(2017.07.15)
- 2017.10.15 noip模拟赛 总结
- 2017/11/3模拟赛总结
- 在Textview中获取指定文字位置(兼顾网址链接和emoji表情),并在其附近展示图片
- node.js常用dos环境命令
- Cocos2dx杂记:cocos 编译命令拷贝so文件
- Hibernate查询语言(HQL)
- POJ 3648 Wedding(2-SAT输出一组解)
- 2017/10/15模拟赛总结
- nfs挂载根文件系统
- 【Vue】 vue2.0父子组件传递函数
- node安装
- vue开发:详解vue.js的devtools安装
- 最常用的DOS命令
- java SpringBoot启动加永无bug图
- NKeditor v5.0.2 发布,在线富文本编辑器
- LDA本地安装和使用实例