2019.11.9 csp-s 考前模拟

是自闭少女lz /lb(泪奔

T1

我可能(呸,一定是唯一一个把这个题写炸了的人

题外话:

我可能是一个面向数据编程选手

作为一个唯一一个写炸T1的人,成功通过多组数据将自己的代码改对/(苦笑

SOLUTION:

对于某个排列的下一个排列,通过我也不知道是感性还是“李”性李姐,我们可以知道,它一定将当前排列最靠后的一个顺序对变成逆序对

倒着看就是找最小的一组逆序对

可以这样理解,从后往前看这个序列,当出现\(a_i<a_{i+1}\)时(由\(a_n\to a_{i+1}\)看a的值是递增的),就一定会出现一个逆序对

然后我们在\(a_{i+1} \to a_n\)中找到最小的\(>=a_i\)的数,交换它们的位置,然后将\(a_{i+1}\to a[n]\)的数按从小到大排序即为答案。

感性李姐

以下是鄙人的垃圾归并排序式代码:

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<algorithm>
  4. #include<cstring>
  5. using namespace std;
  6. inline int read() {
  7. int ans=0;
  8. char last=' ',ch=getchar();
  9. while(ch>'9'||ch<'0') last=ch,ch=getchar();
  10. while(ch>='0'&&ch<='9') ans=(ans<<1)+(ans<<3)+ch-'0',ch=getchar();
  11. if(last=='-') ans=-ans;
  12. return ans;
  13. }
  14. int n,a[100010],d[100010];
  15. int p=214748364,q=-1;
  16. bool msort(int x,int y) {
  17. if(x==y) return 0;
  18. int mid=(x+y)>>1;
  19. bool bj=msort(x,mid);
  20. //因为要优先在最后选取,又因为倒序储存,所以先递归左区间
  21. if(bj) return 1;
  22. int i=x,j=mid+1;
  23. while(i<=mid&&j<=y) {
  24. if((a[i]>a[j]&&q==-1)||(q!=-1&&a[i]>a[q])) {
  25. //找到了正序中满足a_q<=a_{q+1}的a_q或者找到了更小的>a_q的p
  26. p=min(p,i);//找一个下标最小
  27. //因为a_q之后是有序的所以找下标即可
  28. if(q==-1)
  29. q=j;//找到a_q以后就不能再次修改q了
  30. return 1;
  31. } else {
  32. i++;
  33. }
  34. }
  35. msort(mid+1,y);
  36. return 0;
  37. }
  38. bool cmp(int a,int b) {
  39. return a>b;
  40. }
  41. int main() {
  42. freopen("permutation.in","r",stdin);
  43. freopen("permutation.out","w",stdout);
  44. n=read();
  45. for(int i=n;i>=1;i--) {//倒序储存,从原序列的最后开始查找
  46. a[i]=read();
  47. }
  48. msort(1,n);
  49. if(p==214748364&&q==-1) {//是最后一个排列
  50. for(int i=1;i<=n;i++)
  51. printf("%d ",a[i]);
  52. return 0;
  53. }
  54. swap(a[p],a[q]);
  55. sort(a+1,a+q,cmp);
  56. for(int i=n;i>=1;i--)
  57. printf("%d ",a[i]);
  58. return 0;
  59. }

然后附上神仙STD:

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<cstring>
  4. #include<algorithm>
  5. #define N 1000005
  6. using namespace std;
  7. int ai[N];
  8. bool use[N]={false};
  9. int main(){
  10. freopen("permutation.in","r",stdin);
  11. freopen("permutation.out","w",stdout);
  12. int n,i,j,t,nt;
  13. scanf("%d",&n);
  14. for (i=1;i<=n;++i) scanf("%d",&ai[i]);
  15. for (i=n;i;--i)
  16. if (ai[i]!=n-i+1) break;
  17. if (i){
  18. for (i=n;i>1;--i){
  19. use[ai[i]]=true;
  20. if (ai[i-1]<ai[i]){
  21. t=ai[i-1];
  22. for (j=ai[i-1]+1;j<=n;++j)
  23. if (use[j]) break;
  24. ai[i-1]=j;use[j]=false;
  25. use[t]=true;nt=i-1;
  26. for (j=1;j<=n;++j)
  27. if (use[j]) ai[++nt]=j;
  28. break;
  29. }
  30. }for (i=1;i<=n;++i) printf("%d ",ai[i]);
  31. printf("\n");
  32. }else{
  33. for (i=1;i<=n;++i) printf("%d ",i);
  34. printf("\n");
  35. }
  36. fclose(stdin);
  37. fclose(stdout);
  38. }

T2

SOLUTION

30pts 暴力搜索:

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<algorithm>
  4. #include<cstring>
  5. #include<vector>
  6. using namespace std;
  7. inline int read() {
  8. int ans=0;
  9. char last=' ',ch=getchar();
  10. while(ch>'9'||ch<'0') last=ch,ch=getchar();
  11. while(ch>='0'&&ch<='9') ans=(ans<<1)+(ans<<3)+ch-'0',ch=getchar();
  12. if(last=='-') ans=-ans;
  13. return ans;
  14. }
  15. const int mxn=1010;
  16. int n;
  17. int xl;
  18. struct node {
  19. int to,nxt;
  20. }e[mxn<<1];
  21. int ecnt,head[mxn];
  22. void add(int from,int to) {
  23. ++ecnt;
  24. e[ecnt].to=to;
  25. e[ecnt].nxt=head[from];
  26. head[from]=ecnt;
  27. }
  28. vector<int> lj[mxn][mxn],Dfs;
  29. int dep[mxn],siz[mxn],yezi;
  30. int fa[mxn];
  31. void dfs1(int u,int f) {
  32. dep[u]=dep[f]+1;
  33. siz[u]=1;
  34. fa[u]=f;
  35. int maxn=-1;
  36. for(int i=head[u],v;i;i=e[i].nxt) {
  37. v=e[i].to;
  38. if(v==f) continue;
  39. dfs1(v,u);
  40. siz[u]+=siz[v];
  41. }
  42. if(siz[u]==1) yezi++;
  43. }
  44. bool vis[mxn];
  45. void dfs(int u,int from) {
  46. for(int i=0;i<Dfs.size();i++)
  47. lj[from][u].push_back(Dfs[i]);
  48. for(int i=head[u],v;i;i=e[i].nxt) {
  49. v=e[i].to;
  50. if(vis[v]) continue;
  51. vis[v]=1;
  52. Dfs.push_back(v);
  53. dfs(v,from);
  54. Dfs.pop_back();
  55. }
  56. }
  57. int cnt[mxn][mxn];
  58. int main() {
  59. freopen("climb.in","r",stdin);
  60. freopen("climb.out","w",stdout);
  61. n=read();
  62. for(int i=1,u,v;i<n;i++) {
  63. u=read();
  64. v=read();
  65. add(u,v);
  66. add(v,u);
  67. }
  68. dfs1(1,0);
  69. for(int i=1;i<=n;i++){
  70. memset(vis,0,sizeof(vis));
  71. Dfs.push_back(i);
  72. vis[i]=1;
  73. dfs(i,i);
  74. Dfs.pop_back();
  75. }
  76. int ans[mxn<<5],zz;
  77. int nx=1;
  78. ans[1]=1;
  79. zz=1;
  80. bool bj=0;
  81. for(int i=1;i<=yezi;i++) {
  82. xl=read();
  83. for(int j=0,nxx=nx;j<lj[nx][xl].size();j++) {
  84. int v=lj[nx][xl][j];
  85. if(j!=0) {ans[++zz]=v;
  86. cnt[nxx][v]++;
  87. cnt[v][nxx]++;
  88. }
  89. if(cnt[nxx][v]>2||cnt[v][nxx]>2) {
  90. bj=1;
  91. break;
  92. }
  93. nxx=v;
  94. }
  95. nx=xl;
  96. }
  97. for(int j=0,nxx=1;j<lj[nx][1].size();j++) {
  98. int v=lj[nx][1][j];
  99. if(j!=0) {ans[++zz]=v;
  100. cnt[nxx][v]++;
  101. cnt[v][nxx]++;
  102. }
  103. if(cnt[nxx][v]>2||cnt[v][nxx]>2) {
  104. bj=1;
  105. break;
  106. }
  107. nxx=v;
  108. }
  109. if(bj) printf("-1");
  110. else {
  111. for(int i=1;i<=zz;i++)
  112. printf("%d ",ans[i]);
  113. }
  114. return 0;
  115. }

100 pts:

考虑给每个叶子赋值,按照题目中给出的遍历顺序,从小到大分别赋值\(1\to cnt_{yezi}\),记录数组vec[i],表示第i号节点(叶子节点)的遍历顺序(所以好像vec是不满的)对于任意一个节点,维护两个信息:以此节点为根的子树内,vec的最大值和最小值;

如果对一个点来说:\(vec_{max}-vec_{min}\ne siz_{yezi}\)(其中\(siz_{yezi}\)表示以点为根的子树中叶子节点的数量),那么就是无解的,输出‘-1’;(也就是最大最小值之差!=叶子节点个数时无解)

如果有解,如何输出答案?

首先我们必然是先要遍历题中遍历顺序较早的,那么它对应子树的\(vec_{min}\)也会相应较小,因此我们每次遍历\(vec_{min}\)最小的,顺序输出即可;(对于从小到大遍历\(vec\)数组,我们可以采用优先队列的方式)

CODE:

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<algorithm>
  4. #include<cstring>
  5. #include<vector>
  6. #include<queue>
  7. using namespace std;
  8. inline int read() {
  9. int ans=0;
  10. char last=' ',ch=getchar();
  11. while(ch>'9'||ch<'0') last=ch,ch=getchar();
  12. while(ch>='0'&&ch<='9') ans=(ans<<1)+(ans<<3)+ch-'0',ch=getchar();
  13. if(last=='-') ans=-ans;
  14. return ans;
  15. }
  16. const int mxn=101000;
  17. int n;
  18. int num[mxn],xl;
  19. struct E {
  20. int to,nxt;
  21. }e[mxn<<1];
  22. int ecnt,head[mxn];
  23. void add(int from,int to) {
  24. ++ecnt;
  25. e[ecnt].to=to;
  26. e[ecnt].nxt=head[from];
  27. head[from]=ecnt;
  28. }
  29. struct node {
  30. int mx,mn;
  31. }d[mxn];
  32. int dep[mxn],siz[mxn],yezi;
  33. int fa[mxn],Siz[mxn];
  34. bool isye[mxn];
  35. void dfs(int u,int f) {
  36. //printf("%d %d\n",u,f);
  37. Siz[u]=1;
  38. for(int i=head[u],v;i;i=e[i].nxt) {
  39. v=e[i].to;
  40. if(v==f) continue;
  41. dfs(v,u);
  42. Siz[u]+=Siz[v];
  43. }
  44. if(Siz[u]==1) yezi++;
  45. }
  46. bool bj;
  47. void dfs1(int u,int f) {
  48. dep[u]=dep[f]+1;
  49. fa[u]=f;
  50. if(bj==1) return;
  51. d[u].mn=yezi+10;
  52. for(int i=head[u],v;i;i=e[i].nxt) {
  53. v=e[i].to;
  54. if(v==f) continue;
  55. dfs1(v,u);
  56. siz[u]+=siz[v];
  57. d[u].mn=min(d[u].mn,d[v].mn);
  58. d[u].mx=max(d[u].mx,d[v].mx);
  59. }
  60. if(Siz[u]==1) {
  61. siz[u]=1;
  62. d[u].mn=d[u].mx=num[u];
  63. isye[u]=1;
  64. }
  65. if(d[u].mx-d[u].mn+1!=siz[u]) bj=1;
  66. return ;
  67. }
  68. struct Node{
  69. int ll,ord;
  70. }hed;
  71. inline bool operator < (const Node &a,const Node &b)
  72. {
  73. return a.ll>b.ll;
  74. }
  75. void dfs2(int u) {
  76. printf("%d ",u);
  77. if(isye[u])
  78. return;
  79. priority_queue<Node> q;
  80. for(int i=head[u],v;i;i=e[i].nxt) {
  81. v=e[i].to;
  82. if(v==fa[u]) continue;
  83. q.push(Node{d[v].mn,v});
  84. }
  85. while(!q.empty()) {
  86. Node p=q.top();
  87. q.pop();
  88. dfs2(p.ord);
  89. printf("%d ",u);
  90. }
  91. }
  92. int main() {
  93. freopen("climb.in","r",stdin);
  94. freopen("climb.out","w",stdout);
  95. n=read();
  96. for(int i=1,u,v;i<n;i++) {
  97. u=read();
  98. v=read();
  99. add(u,v);
  100. add(v,u);
  101. }
  102. dfs(1,0);
  103. for(int i=1;i<=yezi;i++) {
  104. xl=read();
  105. num[xl]=i;
  106. }
  107. dfs1(1,0);
  108. if(bj==1) printf("-1");
  109. else {
  110. dfs2(1);
  111. }
  112. return 0;
  113. }

T3:

SOLUTION:

对于这道题的solution迷迷糊糊懵懵懂懂说不上不懂,也说不上懂(wtnl

所以我要复制solution了\xk(笑哭

~~题解乱码了* ~~

首先我们要先对两个数组排序

然后通过预处理处理出数组p[i]表示b[x]<a[i]的b的极大个数(讲简单一点就是有多少个b[x]是小于a[i]的

设\(f[i][k]\)表示对于前i个派,至少有k组a[i]>b[j]的方案;

为什么是至少呢?因为在这里我们只是枚举A前i个位置,B的所有位置,并且满足A>B的k个A分配了B,剩余的A与B是没有配对的,而这些人机之间会不会又产生新的配对,我们是没有办法确定的,但我们确认已经有k对了,因此是至少。

那么对于\(f[i][k]=f[i-1][k]+f[i-1][k-1]\times(p[i]-(k-1))\)

如何理解?

\(f[i-1][k]\)表示的是前i-1个派至少有k对\(a_p>b_q\),此时我们不给\(a_i\)配对

\(f[i-1][k-1]\)表示的是前i-1个派至少有k-1对\(a_p>b_q\),这个时候我们需要给\(a_i\)配对,那么可以让\(a_i\)和谁配对呢?显然我们刚刚预处理的p数组就有用了,显然因为序列都是递增的,因此前k-1个\(a_k\)的配对也一定在p[i]数组所包含的范围内,所以除去那k-1个已经与前k-1个\(a_k\)配对的\(b_l\),还有剩余\(p[i]-(k-1)\)个\(b_l\)可供选择,那么\(a_i\)的配对方案就有\(p[i]-(k-1)\)个。

然后这显然不是最后的答案

我们设g[i]表示前n个派,恰好有i组a[x]>b[x];

容斥一下:

\(g[i]=f[n][i]*(n-i)!-g[j]\times C_j^i\)

感性理解:

\(f[n][i]\)分配了i个A,剩余的A与B有\(A_{n-i}^{n-i} \ \ 即 (n-i)!\)种可能的搭配,然后容斥减掉\(g[j]\times C_j^i \ \ \ j\in[i+1,n]\)

最后答案是g[s];

s-(n-s)=k;

得s=(n+k)/2;

n+k为奇数时答案为0;

  1. //放弃挣扎,瞧着可读性极低的std:
  2. #include<iostream>
  3. #include<cstdio>
  4. #include<algorithm>
  5. #define N 2010
  6. #define P 1000000009
  7. using namespace std;
  8. int i,j,a[N],b[N],s[N],n,k,t,p;
  9. long long f[N][N],g[N],c[N][N],fa[N];
  10. int main() {
  11. freopen("pie.in","r",stdin);
  12. freopen("pie.out","w",stdout);
  13. scanf("%d%d",&n,&k);
  14. t=(n+k)/2;
  15. if ((n+k)%2) {
  16. cout<<0<<endl;
  17. return 0;
  18. }
  19. for (i=1;i<=n;i++)
  20. scanf("%d",&a[i]);
  21. for (i=1;i<=n;i++)
  22. scanf("%d",&b[i]);
  23. sort(a+1,a+n+1);
  24. sort(b+1,b+n+1);
  25. for (i=1,p=1;i<=n;i++) {
  26. while(p<=n&&b[p]<a[i])
  27. p++;
  28. s[i]=p-1;
  29. }
  30. for(i=0;i<=n;i++) {
  31. c[i][0]=1;
  32. for(j=1;j<=i;j++)
  33. c[i][j]=(c[i-1][j]+c[i-1][j-1])%P;
  34. }
  35. for(fa[0]=1,i=1;i<=n;i++)
  36. fa[i]=fa[i-1]*i%P;
  37. for(f[0][0]=f[1][0]=1,i=1;i<=n;i++,f[i][0]=1)
  38. for(j=1;j<=i;j++)f[i][j]=(f[i-1][j]+f[i-1][j-1]*max(s[i]-(j-1),0))%P;
  39. for(i=n;i>=t;i--){
  40. g[i]=f[n][i]*fa[n-i]%P;
  41. for(j=i+1;j<=n;j++)
  42. (g[i]+=P-g[j]*c[j][i]%P)%=P;//g[i]=(g[i]-(g[j]*c[j][i]%P)+P)%P
  43. }
  44. cout<<g[t]<<endl;
  45. return 0;
  46. }

2019.11.9 csp-s 考前模拟的更多相关文章

  1. 2019/11/12 CSP模拟赛&&考前小总结

    写在前面的总结 离联赛只有几天了,也马上就要回归文化课了. 有点舍不得,感觉自己的水平刚刚有点起色,却又要被抓回文化课教室了,真想在机房再赖几天啊. 像19/11/11那场的简单题,自己还是能敲出一些 ...

  2. 2019/11/8 CSP模拟

    T1 药品实验 内网#4803 由概率定义,有\[a + b + c = 0\] 变形得到\[1 - b = a + c\] 根据题意有\[p_i = a p _{i - 1} + b p_i + c ...

  3. 2019/11/1 CSP模拟

    写在前面的反思 该拿的部分分还是得拿完啊,因为懒+动作慢没有写最后一道题的菊花图和链的情况,其实这两个点并不难.. 虽然只有\(10pts\),但是已经足够往上爬一截了啊,额外的\(10pts\)在今 ...

  4. 2019.10.26 CSP%您赛第三场

    \(CSP\)凉心模拟^_^ --题源\(lqx.lhc\)等各位蒟蒻 题目名称 比赛 传递消息 开关灯 源文件名 \(competition.cpp\) \(message.cpp\) \(ligh ...

  5. EOJ Monthly 2019.11 E. 数学题(莫比乌斯反演+杜教筛+拉格朗日插值)

    传送门 题意: 统计\(k\)元组个数\((a_1,a_2,\cdots,a_n),1\leq a_i\leq n\)使得\(gcd(a_1,a_2,\cdots,a_k,n)=1\). 定义\(f( ...

  6. [New!!!]欢迎大佬光临本蒟蒻的博客(2019.11.27更新)

    更新于2019.12.22 本蒟蒻在博客园安家啦!!! 本蒟蒻的博客园主页 为更好管理博客,本蒟蒻从今天开始,正式转入博客园. 因为一些原因,我的CSDN博客将彻底不会使用!!!(带来不便,敬请谅解) ...

  7. 2017.11.8 Noip2017 考前模拟赛

    ----------------------------------T1---------------------------------- ——>足球联赛 题目描述 巴蜀中学新一季的足球联赛开 ...

  8. 2017.11.7 Noip2017 考前模拟赛

    ----------------------------------T1---------------------------------- ——>数学老师的报复 题目描述 11 班数学大佬 Y ...

  9. 2019.11.11 模拟赛 T2 乘积求和

    昨天 ych 的膜你赛,这道题我 O ( n4 ) 暴力拿了 60 pts. 这道题的做法还挺妙的,我搞了将近一天呢qwq 题解 60 pts 根据题目给出的式子,四层 for 循环暴力枚举统计答案即 ...

随机推荐

  1. java输出txt文件到桌面

    private static void outputTxt(String ExportFailStudentMsg){ FileSystemView fsv = FileSystemView.getF ...

  2. java浮点数精度问题解决方法

    基础知识回顾: BigDecimal.setScale()方法用于格式化小数点setScale(1)表示保留一位小数,默认用四舍五入方式 setScale(1,BigDecimal.ROUND_DOW ...

  3. AcWing:144. 最长异或值路径(dfs + 01字典树)

    给定一个树,树上的边都具有权值. 树中一条路径的异或长度被定义为路径上所有边的权值的异或和: ⊕ 为异或符号. 给定上述的具有n个节点的树,你能找到异或长度最大的路径吗? 输入格式 第一行包含整数n, ...

  4. xcode6 如何编译64位iOS应用

    原文:http://mobile.51cto.com/hot-412500.htm 随着iPhone5S的推出,大家开始关心5S上所使用的64位CPU A7. 除了关心A7的性能以外,大家还会关心一个 ...

  5. C++入门经典-例6.21-比较string字符串,比较两个字符串

    1:使用“>”.“!=”.“>=”等比较运算符可以比较两个字符串的内容.比较的方法是将两个string字符串从头开始比较每一个字符,直到出现两者不一致.比较这两个不相同的字符的字面值,得出 ...

  6. JS遍历OCX方法

    /----查看OCX组件的属性 <html> <head> <title>OCX</title> <meta http-equiv="C ...

  7. js获取当前时间,并格式化为"yyyy-MM-dd HH:mm:ss"

    /** * Created by Administrator on 2019/11/15. *指尖敲打着世界 ----一个阳光而又不失帅气的少年!!!. */ // js获取当前时间,并格式化为&qu ...

  8. FSCalendar使用和注意事项

    相信大家项目中或多或少都有日历这一块的内容吧,公司作为教育行业的软件公司,当然也是一定有的. 最近被日历这一块的内容弄得很头疼啊,改来改去的,不过还是学到了很多东西,至少FSCalendar的使用基本 ...

  9. mysql实现id自增

    用下面这句话就可以实现插入mysql数据时候实现id自增 create table shuju (id int(10) auto_increment primary key,name varchar( ...

  10. 树莓派 Raspberry Pi 4,.net core 3.0 ,Avalonia UI 开发

    虽说.net core3.0已经可以用于开发wpf和winform程序,可是遗憾的时目前这core下的wpf还是只能运行在windows下,想要在linux下运行wpf估计还要等一段时间. Avalo ...