NOIP2017提高组模拟赛 8(总结)##

第一题 路径

  1. 在二维坐标平面里有N个整数点,Bessie要访问这N个点。刚开始Bessie在点(00)处。 每一步,Bessie可以走到上、下、左、右四个点。即假设Bessie当前所在点的坐标是(x,y),那么它下一步可以移动到(x,y+1), (x,y-1), (x+1,y), (x-1,y)之一。
  2. Bessie目标是找到一个移动序列,满足下面的条件:
  3. 1、从点(0,0)出发。
  4. 2、对于给定的那N个点,每个点至少被访问一次。
  5. 3、可以选择那N个给定点中任意一个作为结束点。
  6. 现在为了增加难度,农夫规定Bessie走过的所有步数之和的奇偶性必须为wantedParity,显然wantedParity 01,是题目给定的,0表示偶,1表示奇。Bessie立刻感觉到了难度的增加,如果存在满足条件的移动序列,那么输出CAN,否则输出CANNOT

  一个定理,假如点i到点j有一条路径是偶数,那么其他路径也一定是偶数(最短距离需要的上下左右是固定的,多余的上和下抵消,多余的左和右抵消),反之亦然。

  简单的证明,假如需要的是偶数,那么只需判断是否存在一个点到(0,0)的距离是偶数就行了(作为终点),其它点可以从(0,0)出发到(xi,yi)再回到(0,0),这样肯定为偶数步数。需要的是奇数的也类似。

  1. #include<cstdio>
  2. #include<algorithm>
  3. #include<cmath>
  4. #define imax(a,b) ((a>b)?(a):(b))
  5. #define imin(a,b) ((a<b)?(a):(b))
  6. typedef long long ll;
  7. using namespace std;
  8. int ng,n,ne,a,b,s[5];
  9. int main()
  10. {
  11. freopen("a.in","r",stdin);
  12. freopen("a.out","w",stdout);
  13. scanf("%d",&ng);
  14. while(ng--)
  15. {
  16. scanf("%d%d",&n,&ne);
  17. s[0]=s[1]=0;
  18. for(int i=1;i<=n;i++)
  19. {
  20. scanf("%d%d",&a,&b);
  21. int c=abs(a)+abs(b);
  22. s[c&1]++;
  23. }
  24. if(ne==0)
  25. {
  26. if(s[0]>0) printf("CAN\n"); else printf("CANNOT\n");
  27. } else
  28. if(ne==1)
  29. {
  30. if(s[1]>0) printf("CAN\n"); else printf("CANNOT\n");
  31. }
  32. }
  33. return 0;
  34. }

第二题 冠军

  1. N个拳手参加擂台赛,这个人的编号是0N-1。有N个位置,编号从0N-1。每个位置分配一个拳手,显然共有N!种不同的分配方案。
  2. 对于一种具体的分配方案,站在位置0的拳手与站在位置1的拳手比赛,胜者进入下一轮,败者被淘汰。站在位置2的拳手与站在位置3的拳手比赛,胜者进入下一轮,败者被淘汰,同样道理,站在位置4的拳手与站在位置5的拳手比赛,胜者进入下一轮,败者被淘汰。。。最终会产生一个冠军拳手。
  3. 如下图所示:

  1. 已知N一定是2的若干次幂,而且不超过16,也就是说N是{2,4,8,16}之中的某一个数。
  2. 现在的问题是:有多少种不同的分配方案,使得第i个选手能最终成为冠军?不妨假设该数值是ans[i]。
  3. 你的任务就是输出:ans[0]、ans[1]、....ans[N-1]。

  一道状压DP题,不过要注意优化,过多的无用状态没过滤掉会被卡。

  若beat[i][j]'Y'  F[S][i]+=F[S1][i]*F[S-S1][j]

  若beat[i][j]'N'  F[S][j]+=F[S1][i]*F[S-S1][j]

  F[S][i]表示选了S这几个拳手(2进制,0为不选,1为选),最终胜利的拳手为i的方案数。

  结果会爆INT,要用LONG LONG来存。

  (PS:一开始,码了搜索去找状态,结果WA了,机子单步不了,又找不出哪里错。后来比赛结束重新码了程序才过。)

  1. #include<cstdio>
  2. #include<algorithm>
  3. #include<cstring>
  4. #include<cmath>
  5. #define imax(a,b) ((a>b)?(a):(b))
  6. #define imin(a,b) ((a<b)?(a):(b))
  7. #define pd(S,i) ((S&(1<<(i-1)))>0)
  8. typedef long long ll;
  9. using namespace std;
  10. const int MP=100500;
  11. int n,hn,nn,B[20],C[20];
  12. char st[20];
  13. bool ff[20][20];
  14. int Go[6][MP],Set[6][MP],one[MP],A[20];
  15. ll f[MP][20];
  16. int main()
  17. {
  18. freopen("b.in","r",stdin);
  19. freopen("b.out","w",stdout);
  20. scanf("%d",&n); hn=n>>1;
  21. nn=(1<<n);
  22. for(int i=1;i<=n;i++)
  23. {
  24. scanf("%s",st);
  25. for(int j=1;j<=n;j++) ff[i][j]=(st[j-1]=='Y');
  26. }
  27. one[0]=0;
  28. for(int i=1;i<nn;i++) one[i]=one[i>>1]+(i&1);
  29. for(int i=1;i<nn;i++)
  30. {
  31. if(one[i]==1) { Set[0][++Set[0][0]]=i; if(i<(1<<2)) Go[0][++Go[0][0]]=i; } else
  32. if(one[i]==2) { Set[1][++Set[1][0]]=i; if(i<(1<<4)) Go[1][++Go[1][0]]=i; } else
  33. if(one[i]==4) { Set[2][++Set[2][0]]=i; if(i<(1<<8)) Go[2][++Go[2][0]]=i; } else
  34. if(one[i]==8) { Set[3][++Set[3][0]]=i; if(i<(1<<16)) Go[3][++Go[3][0]]=i; }
  35. }
  36. for(int i=1;i<=Set[0][0];i++)
  37. {
  38. int S=Set[0][i];
  39. for(int j=1;j<=n;j++)
  40. if(pd(S,j)) f[S][j]=1;
  41. }
  42. Set[4][0]=1; Set[4][1]=(1<<16)-1;
  43. int go=0;
  44. if(n==16) go=4; else
  45. if(n==8) go=3; else
  46. if(n==4) go=2; else go=1;
  47. for(int ho=1;ho<=go;ho++)
  48. {
  49. for(int i=1;i<=Set[ho][0];i++)
  50. {
  51. int S=Set[ho][i],S1; A[0]=0;
  52. for(int j=1;j<=n;j++)
  53. if(pd(S,j)) A[++A[0]]=j;
  54. for(int h=1;h<=Go[ho-1][0];h++)
  55. {
  56. int ss=Go[ho-1][h]; S1=0;
  57. B[0]=0; C[0]=0;
  58. for(int k=1;k<=(1<<ho);k++)
  59. {
  60. if(pd(ss,k))
  61. {
  62. S1|=(1<<(A[k]-1));
  63. B[++B[0]]=A[k];
  64. } else C[++C[0]]=A[k];
  65. }
  66. for(int fa=1;fa<=B[0];fa++)
  67. for(int fb=1;fb<=C[0];fb++)
  68. if(ff[B[fa]][C[fb]]) f[S][B[fa]]+=f[S1][B[fa]]*f[S-S1][C[fb]];
  69. else f[S][C[fb]]+=f[S1][B[fa]]*f[S-S1][C[fb]];
  70. }
  71. }
  72. }
  73. for(int i=1;i<=n;i++) printf("%I64d\n",f[nn-1][i]);
  74. return 0;
  75. }

第三题 指纹

  1. 随着科技的发展,当今很多企业向社会推出了越来越多的结合指纹识别技术的高科技产品。其中以需要进行身份验证或身份识别类型的产品居多,如门禁系统、手提电脑、指纹硬盘。
  2. 对任何生物识别系统来说,输入数据的质量对于系准确率有着重大的影响。为了获得较高质量的指纹图像,近年来指纹采集设备不断地被更新,各种先进的指纹采集技术也逐渐被引入到实际产品中。尽管如此,由于手指皮肤情况、空气湿度、灰尘等一些因素的影响,依旧存在着大量的质量不高的指纹图像。
  3. 通常我们可以通过编号为ABCD的四个属性来评估一个指纹图像的质量的高低:
  4. A为杂点的数量;B为折痕的数量;C为脊线断续程度;D为脊线粘连程度。这四个属性值越小表示该图像在相应方面表现越优。
  5. 由于指纹图质量评估研究的需要,我们通过对一个人的指纹进行多次采样后得到多个不同质量的指纹图像,并将其各质量属性记录在一个数据库中(不同图像的各属性值均不相同)。对于两个指纹图像,单个属性的好坏并不能说明图像质量的高低。比如图像1杂点数比图像2的少,但有可能图像1的粘连程度比图像2高得多,因此不能武断地认为图像1就比图像2好。
  6. 但是如果一个图像有不少于三个属性都优于另一个图像,那么我们有理由相信前者的质量要优于后者。对于数据库中的一个指纹图像I,如果存在另一个图像JJ有不少于三个质量属性优于图像I,那么我们认为图像I是一种“累赘”。
  7. 为了减少指纹图像数据库的大小,我们希望去除其中的累赘图像,现在实验室需要你的帮忙,找出该部分图像。为方便就算,我们已经分别按四个属性,计算出了所有图像按该属性的优劣程度排序的名次。

  这题比前一题好打多了,不过一直在调第二题,这题便没有做……

  每一个指纹有四个参数ABCD

  先考虑ABC,因为假设i的D很小,但ABC很大,那么它也会被刷掉。

  按A排序,用B作为下标,存C。用线段树维护一段区间的最小值。

  A从小到大排序,对于i来说,比它的A小的都已经加入了线段树中,若findmin(1,B)比C小,证明一定存在x的ABC均小于i,那么i也没有存在的意义了(打del标记)。

  再考虑ABD,ACD,BCD,一共四种情况,逐一筛掉无用的指纹就行了。

  1. #include<cstdio>
  2. #include<algorithm>
  3. #include<cmath>
  4. #define imax(a,b) ((a>b)?(a):(b))
  5. #define imin(a,b) ((a<b)?(a):(b))
  6. typedef long long ll;
  7. using namespace std;
  8. const int oo=1e9;
  9. const int N=1e5;
  10. struct data { int a,b,c,d,id; } d[N+100],dg[N+100];
  11. int n;
  12. bool ffg[N+100];
  13. int tree[N<<2];
  14. bool cmp(data A,data B) { return (A.a<B.a); }
  15. void build(int ro,int L,int R)
  16. {
  17. if(L==R) { tree[ro]=oo; return; }
  18. int Mid=(L+R)>>1;
  19. build(ro<<1,L,Mid); build(ro<<1|1,Mid+1,R);
  20. tree[ro]=imin(tree[ro<<1],tree[ro<<1|1]);
  21. }
  22. void pre(int ho)
  23. {
  24. for(int i=1;i<=n;i++) dg[i]=d[i];
  25. if(ho==1) for(int i=1;i<=n;i++) swap(dg[i].c,dg[i].d); else
  26. if(ho==2) for(int i=1;i<=n;i++) swap(dg[i].b,dg[i].d); else
  27. if(ho==3) for(int i=1;i<=n;i++) swap(dg[i].a,dg[i].d);
  28. sort(dg+1,dg+1+n,cmp);
  29. build(1,1,n);
  30. }
  31. void updata(int ro,int L,int R,int x,int val)
  32. {
  33. if(L>x || R<x) return;
  34. if(L==x && x==R)
  35. {
  36. tree[ro]=val; return;
  37. }
  38. int Mid=(L+R)>>1;
  39. updata(ro<<1,L,Mid,x,val); updata(ro<<1|1,Mid+1,R,x,val);
  40. tree[ro]=imin(tree[ro<<1],tree[ro<<1|1]);
  41. }
  42. int query(int ro,int L,int R,int li,int ri)
  43. {
  44. if(L>ri || R<li) return oo;
  45. if(li<=L && R<=ri) return tree[ro];
  46. int Mid=(L+R)>>1;
  47. int x1=query(ro<<1,L,Mid,li,ri),x2=query(ro<<1|1,Mid+1,R,li,ri);
  48. return (imin(x1,x2));
  49. }
  50. int main()
  51. {
  52. freopen("c.in","r",stdin);
  53. freopen("c.out","w",stdout);
  54. scanf("%d",&n);
  55. for(int i=1;i<=n;i++) scanf("%d%d%d%d",&d[i].a,&d[i].b,&d[i].c,&d[i].d),d[i].id=i;
  56. for(int ho=0;ho<4;ho++)
  57. {
  58. pre(ho);
  59. for(int i=1;i<=n;i++)
  60. {
  61. int temp=query(1,1,n,1,dg[i].b);
  62. if(temp<dg[i].c) ffg[dg[i].id]=1;
  63. updata(1,1,n,dg[i].b,dg[i].c);
  64. }
  65. }
  66. int dell=0;
  67. for(int i=1;i<=n;i++) dell+=ffg[i];
  68. printf("%d\n",dell);
  69. for(int i=1;i<=n;i++)
  70. if(ffg[i]) printf("%d\n",i);
  71. return 0;
  72. }

NOIP2017提高组模拟赛 8(总结)的更多相关文章

  1. NOIP2017提高组 模拟赛15(总结)

    NOIP2017提高组 模拟赛15(总结) 第一题 讨厌整除的小明 [题目描述] 小明作为一个数学迷,总会出于数字的一些性质喜欢上某个数字,然而当他喜欢数字k的时候,却十分讨厌那些能够整除k而比k小的 ...

  2. NOIP2017提高组 模拟赛13(总结)

    NOIP2017提高组 模拟赛13(总结) 第一题 函数 [题目描述] [输入格式] 三个整数. 1≤t<10^9+7,2≤l≤r≤5*10^6 [输出格式] 一个整数. [输出样例] 2 2 ...

  3. NOIP2017提高组模拟赛 10 (总结)

    NOIP2017提高组模拟赛 10 (总结) 第一题 机密信息 FJ有个很奇怪的习惯,他把他所有的机密信息都存放在一个叫机密盘的磁盘分区里,然而这个机密盘中却没有一个文件,那他是怎么存放信息呢?聪明的 ...

  4. NOIP2017提高组模拟赛 9 (总结)

    NOIP2017提高组模拟赛 9 (总结) 第一题 星星 天空中有N(1≤N≤400)颗星,每颗星有一个唯一的坐标(x,y),(1≤x,y ≤N).请计算可以覆盖至少K(1≤K≤N)颗星的矩形的最小面 ...

  5. NOIP2017提高组模拟赛 7(总结)

    NOIP2017提高组模拟赛 7(总结) 第一题 斯诺克 考虑这样一个斯诺克球台,它只有四个袋口,分别在四个角上(如下图所示).我们把所有桌子边界上的整数点作为击球点(除了4个袋口),在每个击球点我们 ...

  6. NOIP2017提高组模拟赛5 (总结)

    NOIP2017提高组模拟赛5 (总结) 第一题 最远 奶牛们想建立一个新的城市.它们想建立一条长度为N (1 <= N <= 1,000,000)的 主线大街,然后建立K条 (2 < ...

  7. NOIP2017提高组模拟赛4 (总结)

    NOIP2017提高组模拟赛4 (总结) 第一题 约数 设K是一个正整数,设X是K的约数,且X不等于1也不等于K. 加了X后,K的值就变大了,你可以重复上面的步骤.例如K= 4,我们可以用上面的规则产 ...

  8. 计蒜客NOIP2017提高组模拟赛(三)day1

    火山喷发 火山喷发对所有附近的生物具有毁灭性的影响.在本题中,我们希望用数值来模拟这一过程. 在环境里有 n 个生物分别具有 A​1​​,A​2​​,⋯,A​n​​点生命值,一次火山喷发总计 MM 轮 ...

  9. 计蒜客NOIP2017提高组模拟赛(四)day1

    T1:小X的质数 小 X 是一位热爱数学的男孩子,在茫茫的数字中,他对质数更有一种独特的情感.小 X 认为,质数是一切自然数起源的地方. 在小 X 的认知里,质数是除了本身和 1 以外,没有其他因数的 ...

随机推荐

  1. 【POJ 1733】 Parity Game

    [题目链接] http://poj.org/problem?id=1 [算法] 并查集 [代码] #include <algorithm> #include <bitset> ...

  2. USACO 2.1 Ordered Fractions

    Ordered Fractions Consider the set of all reduced fractions between 0 and 1 inclusive with denominat ...

  3. 解析RecyclerView(2)——带顶部View和底部View的RecyclerView

    在网络层,互联网提供所有应用程序都要使用的两种类型的服务,尽管目前理解这些服务的细节并不重要,但在所有TCP/IP概述中,都不能忽略他们: 无连接分组交付服务(Connectionless Packe ...

  4. <Android Framework 之路>Android5.1 Camera Framework(三)

    上一次讲解了一下startPreview过程,主要是为了画出一条大致的从上到下的线条,今天我们看一下Camera在Framework的sendCommand和dataCallback,这部分属于衔接过 ...

  5. Java标识符规范

    1.标识符用来定义包名,类名,方法名,变量名,常量名. 2.标识符必须由字母.下划线.$符号组成,不能以数字开头.不能是Java中的保留关键字.

  6. JavaScript大纲

  7. TESTUSERB 仅能对TESTUSERA 用户下的某些表增删改查、有些表仅能对某些列update,查询TESTUSERB 用户权限,获取批量赋予语句。

    TESTUSERB 仅能对TESTUSERA 用户下的某些表增删改查.有些表仅能对某些列update,查询TESTUSERB 用户权限,获取批量赋予语句. select 'grant '|| PRIV ...

  8. easyui的增删改

    陈旧的开发模式PM:“我要这个功能”后端:“这个先找前端做个模板”前端:“模板做完了”后端:“我来对接一下,这里样式不对”前端:“我改完了”后端:“功能交付”PM:“春节要加这个活动”后端:“这个先找 ...

  9. 路飞学城Python-Day20(元类的练习题)

    练习一:在元类中控制把自定义类的数据属性都变成大写 class MyDef(type): def __new__(cls, class_name, class_attr, class_dic): up ...

  10. js倒计时demo 天/时/分/秒

    <html><head> <meta charset="UTF-8"> <title>js简单时分秒倒计时</title> ...