A.入阵曲

部分分很肥,正解写得常数稍大就会和暴力一个分,考试的时候写什么自己考虑。(滑稽

部分分的循环边界手抖写错了-25 (原本暴力分中的10分都没了啊啊啊)

没写挂的话应该有75,其实就是二维前缀和+暴力枚举点对统计+$a[i][j]$都相等时只枚举子矩形大小再乘上这种大小出现的次数。

正解:$(sum[r]-sum[l-1])\% K=0 \rightarrow sum[r]\% K=sum[l-1]\% K$

枚举行数$i,j$和列数$k$,维护i行和j行之间、k列左侧在%K意义下同余矩阵的个数,用桶来实现。

  1. #include<cstdio>
  2. #include<iostream>
  3. #include<cstring>
  4. using namespace std;
  5. typedef long long ll;
  6. const int N=;
  7. int n,m;
  8. ll K,ans;
  9. int a[N][N];
  10. ll sum[N][N],sum1[N],cnt[];
  11. int read()
  12. {
  13. int x=,f=;char ch=getchar();
  14. while(!isdigit(ch)){if(ch=='-')f=-;ch=getchar();}
  15. while(isdigit(ch))x=x*+ch-'',ch=getchar();
  16. return x*f;
  17. }
  18.  
  19. int main()
  20. {
  21. n=read();m=read();K=1LL*read();
  22. for(int i=;i<=n;i++)
  23. for(int j=;j<=m;j++)
  24. a[i][j]=read();
  25. for(int i=;i<=n;i++)
  26. for(int j=;j<=m;j++)
  27. sum[i][j]=sum[i-][j]+sum[i][j-]-sum[i-][j-]+1LL*a[i][j];
  28. for(int i=;i<n;i++)
  29. for(int j=i+;j<=n;j++)
  30. {
  31. cnt[]=;
  32. for(int k=;k<=m;k++)
  33. {
  34. sum1[k]=(sum[j][k]-sum[i][k]+K)%K;
  35. ans+=cnt[sum1[k]];
  36. cnt[sum1[k]]++;
  37. }
  38. for(int k=;k<=m;k++)cnt[sum1[k]]=;
  39. }
  40. cout<<ans<<endl;
  41. return ;
  42. }

B.将军令

我考场都能想到的sb贪心。每次取出深度最大且未被覆盖的点,在它的K级祖先上驻扎即可。前者用堆维护,后者直接暴力修改覆盖状态,注意向上修改时不要只遍历和它在一条链上的。

正确性?读者自证不难。(逃

  1. #include<cstdio>
  2. #include<iostream>
  3. #include<cstring>
  4. #include<queue>
  5. #define pa pair<int,int>
  6. #define re register
  7. using namespace std;
  8. int read()
  9. {
  10. int x=,f=;char ch=getchar();
  11. while(!isdigit(ch)){if(ch=='-')f=-;ch=getchar();}
  12. while(isdigit(ch))x=x*+ch-'',ch=getchar();
  13. return x*f;
  14. }
  15. const int N=;
  16. int n,K,t;
  17. int to[N<<],nxt[N<<],head[N],tot;
  18. inline void add(int x,int y)
  19. {
  20. to[++tot]=y;
  21. nxt[tot]=head[x];
  22. head[x]=tot;
  23. }
  24. int dep[N],fa[N];
  25. priority_queue<pa> q;
  26. void dfs1(int x,int deep)
  27. {
  28. dep[x]=deep;
  29. for(re int i=head[x];i;i=nxt[i])
  30. {
  31. int y=to[i];
  32. if(!dep[y])dfs1(y,deep+),fa[y]=x;
  33. }
  34. return ;
  35. }
  36. int cover[N],anc,ans;
  37. void getan(int x,int rest)
  38. {
  39. if(!rest||x==)
  40. {
  41. anc=x;
  42. return ;
  43. }
  44. getan(fa[x],rest-);
  45. return ;
  46. }
  47. void dfs2(int x,int rest,int f)
  48. {
  49. cover[x]=;
  50. if(!rest)return ;
  51. for(re int i=head[x];i;i=nxt[i])
  52. {
  53. int y=to[i];
  54. if(y==f)continue;
  55. dfs2(y,rest-,x);
  56. }
  57. return ;
  58. }
  59.  
  60. int main()
  61. {
  62. n=read();K=read();t=read();
  63. for(re int i=;i<n;i++)
  64. {
  65. int x=read(),y=read();
  66. add(x,y);add(y,x);
  67. }
  68. dfs1(,);
  69. for(re int i=;i<=n;i++)
  70. q.push(make_pair(dep[i],i));
  71. while(!q.empty())
  72. {
  73. int x=q.top().second;
  74. q.pop();
  75. if(cover[x])continue;
  76. getan(x,K);
  77. //cout<<anc<<endl;
  78. dfs2(anc,K,-);
  79. ans++;
  80. }
  81. cout<<ans<<endl;
  82. return ;
  83. }

C.星空

区间状态反转可以看作区间异或1,但区间操作不好处理,考虑通过差分转化为单点操作。即把对原数组上$[L,R]$区间的操作转化为差分数组上$L-1$和$R$两个点的操作。这里用到了异或差分:$dif[i]=a[i]\ xor\ a[i+1]$

所以问题变成了:有一个01串,每次对其中两个点$xor\ 1$,需要多少次把这个串的每一位都变成0。(差分数组全0对应原数组全1)

可以发现,消去两个1的费用与他们之间的距离有关。bfs预处理出来后,问题再次得到转化:每次取出一对物品,每对物品取出都有一定代价,如何取出使得代价最小。由于不亮的灯泡很少,这个问题完全可以状压解决。

  1. #include<cstdio>
  2. #include<iostream>
  3. #include<cstring>
  4. #include<queue>
  5. #include<vector>
  6. using namespace std;
  7. int read()
  8. {
  9. int x=,f=;char ch=getchar();
  10. while(!isdigit(ch)){if(ch=='-')f=-;ch=getchar();}
  11. while(isdigit(ch))x=x*+ch-'',ch=getchar();
  12. return x*f;
  13. }
  14. const int N=;
  15. int n,m,K;
  16. int a[N],op[N],dif[N];
  17. int pos[N],sz;
  18. int vis[N],dis[][],d[N];
  19. int find0[N<<],dp[N<<];
  20. void bfs(int node)
  21. {
  22. memset(d,,sizeof(d));
  23. memset(vis,,sizeof(vis));
  24. queue<int> q;
  25. q.push(node);
  26. vis[node]=;d[node]=;
  27. while(!q.empty())
  28. {
  29. int x=q.front();
  30. q.pop();
  31. for(int i=;i<=m;i++)
  32. {
  33. int s1=x+op[i],s2=x-op[i];
  34. if(s1<=n&&!vis[s1])
  35. {
  36. q.push(s1);
  37. d[s1]=d[x]+;
  38. vis[s1]=;
  39. }
  40. if(s2>=&&!vis[s2])
  41. {
  42. q.push(s2);
  43. d[s2]=d[x]+;
  44. vis[s2]=;
  45. }
  46. }
  47. }
  48. }
  49.  
  50. int main()
  51. {
  52. n=read();K=read();m=read();
  53. for(int i=;i<=K;i++)
  54. a[read()]=;
  55. for(int i=;i<=m;i++)
  56. op[i]=read();
  57. for(int i=;i<=n;i++)
  58. {
  59. dif[i]=a[i]^a[i+];
  60. if(dif[i])pos[++sz]=i;
  61. }
  62. for(int i=;i<=sz;i++)
  63. {
  64. bfs(pos[i]);
  65. for(int j=;j<=sz;j++)
  66. dis[i][j]=d[pos[j]];
  67. }
  68. for(int s=;s<(<<sz);s++)
  69. {
  70. find0[s]=sz-;
  71. for(int i=;i<sz;i++)
  72. if(((s>>i)&)==)
  73. {
  74. find0[s]=i;
  75. break;
  76. }
  77. }
  78. memset(dp,0x3f,sizeof(dp));
  79. dp[]=;
  80. for(int s=;s<(<<sz);s++)
  81. for(int i=find0[s]+;i<sz;i++)
  82. {
  83. if(((s>>i)&)==&&dis[find0[s]+][i+])
  84. {
  85. int now=(s|(<<find0[s])|(<<i));
  86. dp[now]=min(dp[now],dp[s]+dis[find0[s]+][i+]);
  87. //cout<<dp[now]<<endl;
  88. }
  89. }
  90. cout<<dp[(<<sz)-]<<endl;
  91. return ;
  92. }

[NOIP]模拟17 题解的更多相关文章

  1. NOIP模拟17.9.21

    NOIP模拟17.9.21 3 58 145 201 161.5 样例输出21.6 数据规模及约定对于40% 的数据,N <= 20对于60% 的数据,N <= 1000对于100% 的数 ...

  2. NOIP模拟17.9.22

    NOIP模拟17.9.22 前进![问题描述]数轴的原点上有一只青蛙.青蛙要跳到数轴上≥

  3. NOIP模拟 17.8.20

    NOIP模拟17.8.20 A.阶乘[题目描述]亲爱的xyx同学正在研究数学与阶乘的关系,但是他喜欢颓废,于是他就制作了一个和阶乘有关系的数学游戏:给出两个整数 n,m,令 t = !n,每轮游戏的流 ...

  4. NOIP模拟 17.8.18

    NOIP模拟17.8.18 A.小菜一碟的背包[题目描述]Blice和阿强巴是好朋友但萌萌哒Blice不擅长数学,所以阿强巴给了她一些奶牛做练习阿强巴有 n头奶牛,每头奶牛每天可以产一定量的奶,同时也 ...

  5. NOIP模拟 17.8.15

    NOIP模拟17.8.15 A 债务文件名 输入文件 输出文件 时间限制 空间限制debt.pas/c/cpp debt.in debt.out 1s 128MB[题目描述]小 G 有一群好朋友,他们 ...

  6. NOIP模拟 17.8.17

    NOIP模拟17.8.17 A 小 G 的字符串文件名 输入文件 输出文件 时间限制 空间限制str.pas/c/cpp str.in str.out 1s 128MB[题目描述]有一天,小 L 给小 ...

  7. NOIP模拟 17.8.16

    NOIP模拟17.8.16 A 债务文件名 输入文件 输出文件 时间限制 空间限制debt.pas/c/cpp debt.in debt.out 1s 128MB[题目描述]小 G 有一群好朋友,他们 ...

  8. NOIP模拟 17.8.14

    NOIP模拟17.8.14 (天宇哥哥考察细心程度的题) [样例解释]如果删去第一个 1:在[3,1,2]中有 3 个不同的数如果删去 3:在[1,1,2]中有 2 个不同的数如果删去第二个 1:在[ ...

  9. 大家AK杯 灰天飞雁NOIP模拟赛题解/数据/标程

    数据 http://files.cnblogs.com/htfy/data.zip 简要题解 桌球碰撞 纯模拟,注意一开始就在袋口和v=0的情况.v和坐标可以是小数.为保险起见最好用extended/ ...

随机推荐

  1. C#排列组合类,写彩票算法的朋友们可以来看一看

    public class PermutationAndCombination<T>    {        /// <summary>        /// 交换两个变量    ...

  2. jenkins安装-配置

    jenkins安装-配置 注意: jenkins访问 用chrome浏览器 安装包下载:http://pkg.jenkins-ci.org/redhat/ (使用2.92版本的) 安装jdk: 1.8 ...

  3. PHP如何进行错误与异常处理(PHP7中的异常处理和之前版本异常处理的区别)

    PHP如何进行错误与异常处理(PHP7中的异常处理和之前版本异常处理的区别) 一.总结 一句话总结: throwable接口+Error类 在PHP7更新中有一条:更多的Error变为可捕获的Exce ...

  4. python自动化之函数封装

    函数最重要的目的是方便我们重复使用相同的一段程序. 将一些操作隶属于一个函数,以后你想实现相同的操作的时候,只用调用函数名就可以,而不需要重复敲所有的语句. 前面一些记录了selenium的各种API ...

  5. HTML5: HTML5 拖放

    ylbtech-HTML5: HTML5 拖放 1.返回顶部 1. HTML5 拖放(Drag 和 Drop) 拖放(Drag 和 drop)是 HTML5 标准的组成部分.   将 RUNOOB.C ...

  6. toString()方法,与call()方法结合;用来进行数据类型检测

    ​ //toString()方法,与call()方法结合;用来进行数据类型检测 console.log(Object.prototype.toString.call([]));//'[object A ...

  7. Spring JDBC FOUND_ROWS 安全吗?

    在很多分页的程序中都这样写: SELECT COUNT(*) from `table` WHERE ......;  查出符合条件的记录总数 SELECT * FROM `table` WHERE . ...

  8. 20-python基础-python3-reversed()函数

    描述 reversed 函数返回一个反转的迭代器. 语法 reversed(seq) 参数 seq -- 要转换的序列,可以是 tuple, string, list 或 range. # 字符串 s ...

  9. React-Native 使用中的坑

    android 1.键盘会在 ScrollView 之上----不知道是不是未给ScrollView 设置高度的问题 2.navigation的标题在android居中显示办法 navigationO ...

  10. android 拖拉和放大

    public class MainActivity extends Activity { private ImageView imageView; @Override public void onCr ...