点此进入比赛

得分: \(100+20+100=220\)(还不错)

排名: \(Rank\ 16\)

\(Rating\):\(+20\)

\(T1\):【HHHOJ263】「NOIP模拟赛 玖」三个和尚(点此看题面

第一眼看完毫无想法。

仔细思考,可以发现一个性质:只要原数数位之和\(sum\)不能被\(3\)整除,就说明无解

然后就很简单了,只要使输出的\(3\)个数数位之和全部为\(\frac{sum}3\)即可。

代码如下:

  1. #include<bits/stdc++.h>
  2. #define max(x,y) ((x)>(y)?(x):(y))
  3. #define min(x,y) ((x)<(y)?(x):(y))
  4. #define uint unsigned int
  5. #define LL long long
  6. #define ull unsigned long long
  7. #define swap(x,y) (x^=y,y^=x,x^=y)
  8. #define abs(x) ((x)<0?-(x):(x))
  9. #define INF 1e9
  10. #define Inc(x,y) ((x+=(y))>=MOD&&(x-=MOD))
  11. #define ten(x) (((x)<<3)+((x)<<1))
  12. #define N 10000
  13. using namespace std;
  14. int n=0,num[N+5];
  15. class FIO
  16. {
  17. private:
  18. #define Fsize 100000
  19. #define tc() (FinNow==FinEnd&&(FinEnd=(FinNow=Fin)+fread(Fin,1,Fsize,stdin),FinNow==FinEnd)?EOF:*FinNow++)
  20. #define pc(ch) (FoutSize<Fsize?Fout[FoutSize++]=ch:(fwrite(Fout,1,FoutSize,stdout),Fout[(FoutSize=0)++]=ch))
  21. int f,FoutSize,OutputTop;char ch,Fin[Fsize],*FinNow,*FinEnd,Fout[Fsize],OutputStack[Fsize];
  22. public:
  23. FIO() {FinNow=FinEnd=Fin;}
  24. inline void read(int &x) {x=0,f=1;while(!isdigit(ch=tc())) f=ch^'-'?1:-1;while(x=ten(x)+(ch&15),isdigit(ch=tc()));x*=f;}
  25. inline bool read_digit(int &x) {while(!isdigit(x=tc())) if(!~x) return false;return x&=15,true;}
  26. inline void read_char(char &x) {while(isspace(x=tc()));}
  27. inline void read_string(string &x) {x="";while(isspace(ch=tc()));while(x+=ch,!isspace(ch=tc())) if(!~ch) return;}
  28. inline void write(int x) {if(!x) return (void)pc('0');if(x<0) pc('-'),x=-x;while(x) OutputStack[++OutputTop]=x%10+48,x/=10;while(OutputTop) pc(OutputStack[OutputTop]),--OutputTop;}
  29. inline void write_char(char x) {pc(x);}
  30. inline void write_string(string x) {register int i,len=x.length();for(i=0;i<len;++i) pc(x[i]);}
  31. inline void end() {fwrite(Fout,1,FoutSize,stdout);}
  32. }F;
  33. inline void Solve(int x,int v)//x表示当前处理到的位数,v表示剩余的数位和
  34. {
  35. if(num[x]>=v) return (void)(F.write_char(v+48),num[x]-=v);//如果该位数字≥v,就输出v,并将该位数字减去v
  36. Solve(x-1,v-num[x]),F.write_char(num[x]+48),num[x]=0;//如果该位数字<v,就处理更高的一位,然后输出该位数字(注意,这顺序不能反),然后将该位数字赋值为0
  37. }
  38. int main()
  39. {
  40. register int i,x,sum=0;
  41. while(F.read_digit(x)) sum+=(num[++n]=x);//用sum统计数位之和
  42. if(sum%3) return puts("-1"),0;//如果sum不能被3整除,说明无解
  43. for(i=1;i<=3;++i) Solve(n,sum/3),F.write_char(' ');//输出答案
  44. return F.end(),0;
  45. }

\(T2\):【HHHOJ264】「NOIP模拟赛 玖」疯狂祖玛(点此看题面

比赛时写了一个区间\(DP\),样例水过,交上去挂了,只有\(20\)分... ...

正解貌似是一个更加高级的区间\(DP\),但是要用记忆化搜索实现,思路十分巧妙。

为了简便,我们可以用\(NeedBall(x)\)表示有\(x\)个颜色相同且连续的珠子时还需加多少个珠子才能将其消掉。具体实现如下:

  1. #define NeedBall(x) ((x)<k?k-(x):0)

首先,我们把颜色相同且连续的珠子压缩在一起,用\(col_i\)表示颜色,\(num_i\)表示个数。

然后,考虑用\(f_{l,r,v}\)表示在编号为\(r\)的珠子右边有\(v\)个与\(r\)号珠子同色的珠子时,要把\([l,r]\)区间内的珠子消完所需要增加的最少珠子数

则有两种转移方式:

  • 直接加上\(Need(v+num_r)\)个珠子把\(r\)号珠子消掉。即\(f_{l,r,v}=f_{l,r-1,0}+Need(v+num_r)\)。
  • 找到\([l,r]\)范围内的一个\(i\)使其满足\(col_i=col_r\),我们可以选择将\([i+1,r-1]\)之间的珠子消掉,然后将\(i\)和\(r\)两块珠子连在一起。即\(f_{l,r,v}=min(f_{l,r,v},f_{l,i,min(k,v+num_r)}+f_{i+1,r-1,0})\)。

代码如下:

  1. #include<bits/stdc++.h>
  2. #define max(x,y) ((x)>(y)?(x):(y))
  3. #define min(x,y) ((x)<(y)?(x):(y))
  4. #define uint unsigned int
  5. #define LL long long
  6. #define ull unsigned long long
  7. #define swap(x,y) (x^=y,y^=x,x^=y)
  8. #define abs(x) ((x)<0?-(x):(x))
  9. #define INF 1e9
  10. #define Inc(x,y) ((x+=(y))>=MOD&&(x-=MOD))
  11. #define ten(x) (((x)<<3)+((x)<<1))
  12. #define N 100
  13. #define K 5
  14. #define AddBalls(y,z) (s[++n]=Balls(y,z),lst[n]=End[y],End[y]=n)
  15. #define NeedBall(x) ((x)<k?k-(x):0)//求出还需多少个球
  16. using namespace std;
  17. int n,k,lst[N+5],End[N+5];
  18. struct Balls//记录连续一段颜色相同的求的信息
  19. {
  20. int col,num;//col记录颜色,num记录数量
  21. Balls(int x=0,int y=0):col(x),num(y){}
  22. }s[N+5];
  23. class FIO
  24. {
  25. private:
  26. #define Fsize 100000
  27. #define tc() (FinNow==FinEnd&&(FinEnd=(FinNow=Fin)+fread(Fin,1,Fsize,stdin),FinNow==FinEnd)?EOF:*FinNow++)
  28. #define pc(ch) (FoutSize<Fsize?Fout[FoutSize++]=ch:(fwrite(Fout,1,FoutSize,stdout),Fout[(FoutSize=0)++]=ch))
  29. int f,FoutSize,OutputTop;char ch,Fin[Fsize],*FinNow,*FinEnd,Fout[Fsize],OutputStack[Fsize];
  30. public:
  31. FIO() {FinNow=FinEnd=Fin;}
  32. inline void read(int &x) {x=0,f=1;while(!isdigit(ch=tc())) f=ch^'-'?1:-1;while(x=ten(x)+(ch&15),isdigit(ch=tc()));x*=f;}
  33. inline void read_char(char &x) {while(isspace(x=tc()));}
  34. inline void read_string(string &x) {x="";while(isspace(ch=tc()));while(x+=ch,!isspace(ch=tc())) if(!~ch) return;}
  35. inline void write(int x) {if(!x) return (void)pc('0');if(x<0) pc('-'),x=-x;while(x) OutputStack[++OutputTop]=x%10+48,x/=10;while(OutputTop) pc(OutputStack[OutputTop]),--OutputTop;}
  36. inline void write_char(char x) {pc(x);}
  37. inline void write_string(string x) {register int i,len=x.length();for(i=0;i<len;++i) pc(x[i]);}
  38. inline void end() {fwrite(Fout,1,FoutSize,stdout);}
  39. }F;
  40. class Class_DP
  41. {
  42. private:
  43. int f[N+5][N+5][K+5];//f[l][r][v]表示在编号为r的珠子右边有v个与r号珠子同色的珠子时,要把[l,r]区间内的珠子消完所需要增加的最少珠子数
  44. public:
  45. inline void Init() {for(register int i=0,j,l;i<=n;++i) for(j=i;j<=n;++j) for(l=0;l<=k;++l) f[i][j][l]=-1;}//初始化全部为-1,方便记忆化
  46. inline int GetAns(int l,int r,int v)//记忆化搜索
  47. {
  48. if(~f[l][r][v]) return f[l][r][v];//如果已经求解过,返回求出的答案
  49. register int i,t;
  50. for(f[l][r][v]=GetAns(l,r-1,0)+NeedBall(s[r].num+v),i=l;i<r;++i)
  51. if(!(s[i].col^s[r].col)) t=GetAns(l,i,min(k,s[r].num+v))+GetAns(i+1,r-1,0),f[l][r][v]=min(f[l][r][v],t);//状态转移
  52. return f[l][r][v];
  53. }
  54. }DP;
  55. int main()
  56. {
  57. register int i,nn,x,y,z=1;
  58. for(F.read(nn),F.read(k),F.read(y),--nn;nn;--nn) F.read(x),(x^y?(AddBalls(y,z),y=x,z=1):++z);
  59. return AddBalls(y,z),DP.Init(),F.write(DP.GetAns(1,n,0)),F.end(),0;//输出答案
  60. }

\(T3\):【HHHOJ265】「NOIP模拟赛 玖」回文单词(点此看题面

说实话,这题就是一个比较简单的哈希

考虑题意,其实不难有一个贪心的想法:每次选取最短的相同的前缀和后缀,将其从字符串中删去,并将答案加\(1\)。

关于如何求出最短的相同的前缀和后缀,我首先想到的是利用\(KMP\)算法的\(Next\)数组。

后来发现不行(因为前缀是在变化的)。

所以我们要用更灵活的字符串匹配方式:字符串哈希

个人感觉得出上面那个结论,这道题就不难了。

具体实现可以看下面的代码:

  1. #include<bits/stdc++.h>
  2. #define max(x,y) ((x)>(y)?(x):(y))
  3. #define min(x,y) ((x)<(y)?(x):(y))
  4. #define uint unsigned int
  5. #define LL long long
  6. #define ull unsigned long long
  7. #define swap(x,y) (x^=y,y^=x,x^=y)
  8. #define abs(x) ((x)<0?-(x):(x))
  9. #define INF 1e9
  10. #define Inc(x,y) ((x+=(y))>=MOD&&(x-=MOD))
  11. #define ten(x) (((x)<<3)+((x)<<1))
  12. #define N 1000000
  13. using namespace std;
  14. string st;
  15. class FIO
  16. {
  17. private:
  18. #define Fsize 100000
  19. #define tc() (FinNow==FinEnd&&(FinEnd=(FinNow=Fin)+fread(Fin,1,Fsize,stdin),FinNow==FinEnd)?EOF:*FinNow++)
  20. #define pc(ch) (FoutSize<Fsize?Fout[FoutSize++]=ch:(fwrite(Fout,1,FoutSize,stdout),Fout[(FoutSize=0)++]=ch))
  21. int f,FoutSize,OutputTop;char ch,Fin[Fsize],*FinNow,*FinEnd,Fout[Fsize],OutputStack[Fsize];
  22. public:
  23. FIO() {FinNow=FinEnd=Fin;}
  24. inline void read(int &x) {x=0,f=1;while(!isdigit(ch=tc())) f=ch^'-'?1:-1;while(x=ten(x)+(ch&15),isdigit(ch=tc()));x*=f;}
  25. inline void read_char(char &x) {while(isspace(x=tc()));}
  26. inline void read_string(string &x) {x="";while(isspace(ch=tc()));while(x+=ch,!isspace(ch=tc())) if(!~ch) return;}
  27. inline void write(int x) {if(!x) return (void)pc('0');if(x<0) pc('-'),x=-x;while(x) OutputStack[++OutputTop]=x%10+48,x/=10;while(OutputTop) pc(OutputStack[OutputTop]),--OutputTop;}
  28. inline void write_char(char x) {pc(x);}
  29. inline void write_string(string x) {register int i,len=x.length();for(i=0;i<len;++i) pc(x[i]);}
  30. inline void end() {fwrite(Fout,1,FoutSize,stdout);}
  31. }F;
  32. class Class_HashSolver//用字符串哈希求解答案
  33. {
  34. private:
  35. struct Hash//双哈希
  36. {
  37. ull fir,sec;
  38. Hash(ull x=0,ull y=0):fir(x),sec(y){}
  39. }seed,s[N+5],t[N+5];
  40. inline friend Hash operator + (Hash x,Hash y) {return Hash(x.fir+y.fir,x.sec+y.sec);}//重载加法
  41. inline friend Hash operator - (Hash x,Hash y) {return Hash(x.fir-y.fir,x.sec-y.sec);}//重载减法
  42. inline friend Hash operator * (Hash x,Hash y) {return Hash(x.fir*y.fir,x.sec*y.sec);}//重载乘法
  43. inline friend bool operator == (Hash x,Hash y) {return !(x.fir^y.fir||x.sec^y.sec);}//重载等于号
  44. public:
  45. Class_HashSolver() {seed=Hash(31,41),t[0]=Hash(1,1);for(register int i=1;i<=N;++i) t[i]=t[i-1]*seed;}//初始化
  46. inline void Init(string st) {s[0]=Hash(1,1);for(register int i=1,len=st.length();i<=len;++i) s[i]=s[i-1]*seed+Hash(st[i-1]&31,st[i-1]&31);}//对字符串进行哈希
  47. inline bool check(int l1,int r1,int l2,int r2) {return (s[r1]-(s[l1-1]*t[r1-l1+1]))==(s[r2]-(s[l2-1]*t[r2-l2+1]));}//比较两段区间内的字符串是否相同
  48. inline int GetAns(int l,int r)//求解[l,r]区间内的答案
  49. {
  50. if(l>r) return 0;
  51. for(register int i=l;(i<<1)<(l+r);++i) if(check(l,i,l+r-i,r)) return GetAns(i+1,l+r-i-1)+2;//找到最短的相同的前缀和后缀,将其从字符串中删去,并将答案加2
  52. return 1;//否则,这整个字符串对答案造成的贡献为1
  53. }
  54. }HashSolver;
  55. int main()
  56. {
  57. register int T;F.read(T);
  58. while(T--) F.read_string(st),HashSolver.Init(st),F.write(HashSolver.GetAns(1,st.length())),F.write_char('\n');
  59. return F.end(),0;
  60. }

【HHHOJ】NOIP模拟赛 玖 解题报告的更多相关文章

  1. 【HHHOJ】NOIP模拟赛 捌 解题报告

    点此进入比赛 得分: \(30+30+70=130\)(弱爆了) 排名: \(Rank\ 22\) \(Rating\):\(-31\) \(T1\):[HHHOJ260]「NOIP模拟赛 捌」Dig ...

  2. 20161005 NOIP 模拟赛 T2 解题报告

    beautiful 2.1 题目描述 一个长度为 n 的序列,对于每个位置 i 的数 ai 都有一个优美值,其定义是:找到序列中最 长的一段 [l, r],满足 l ≤ i ≤ r,且 [l, r] ...

  3. CH Round #55 - Streaming #6 (NOIP模拟赛day2)解题报告

    T1九九归一 描述 萌蛋在练习模n意义下的乘法时发现,总有一些数,在自乘若干次以后,会变成1.例如n=7,那么5×5 mod 7=4,4×5 mod 7=6,6×5 mod 7=2,2×5 mod 7 ...

  4. CH Round #54 - Streaming #5 (NOIP模拟赛Day1)解题报告

    最近参加了很多CH上的比赛呢~Rating--了..题目各种跪烂.各种膜拜大神OTZZZ T1珠 描述 萌蛋有n颗珠子,每一颗珠子都写有一个数字.萌蛋把它们用线串成了环.我们称一个数字串是有趣的,当且 ...

  5. 20161007 NOIP 模拟赛 T1 解题报告

    排序 3.1 题意描述 众所周知,熟练掌握至少一种排序算法是参加NOIP的必备技能.常见的排序算法有冒泡 排序.归并排序.快速排序.奇偶排序.猴子排序.梳排序.鸡尾酒排序.臭皮匠排序等. 在这里,介绍 ...

  6. 20161003 NOIP 模拟赛 T2 解题报告

    Weed duyege的电脑上面已经长草了,经过辨认上面有金坷垃的痕迹. 为了查出真相,duyege 准备修好电脑之后再进行一次金坷垃的模拟实验. 电脑上面有若干层金坷垃,每次只能在上面撒上一层高度为 ...

  7. 20161005 NOIP 模拟赛 T3 解题报告

    subset 3.1 题目描述 一开始你有一个空集,集合可以出现重复元素,然后有 Q 个操作 1. add s 在集合中加入数字 s. 2. del s 在集合中删除数字 s.保证 s 存在 3. c ...

  8. 【BLUESKY的NOIp模拟赛】解题报告

     昨天晚上熬夜熬得有点严重,今天比赛的时候状态不好,成绩爆炸...  不得不说BLUESKY007 出的题还是相当不错的,也为我提醒了几个需要补的漏洞方向,这里作一下整理. \(Task 1\):探索 ...

  9. 20161022 NOIP模拟赛 T1 解题报告

    旅行者问题 [问题描述] lahub是一个旅行者的粉丝,他想成为一个真正的旅行者,所以他计划开始一段旅行.lahub想去参观n个目的地(都在一条直道上).lahub在起点开始他的旅行.第i个目的地和起 ...

随机推荐

  1. Codeforces Round #527 (Div. 3)D2(栈,思维)

    #include<bits/stdc++.h>using namespace std;int a[200007];stack<int>s;int main(){    int ...

  2. 清北刷题冲刺 11-03 a.m

    纸牌 #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> ...

  3. layui的tree和form并没有冲突!无限级tree下拉列表和select下拉列表同一页使用!

    在昨天写的随笔中: layui的tree和form同时引用出现冲突的粗略解决办法 https://www.cnblogs.com/xwma/p/10900975.html 提出有冲突,今天在开发中发现 ...

  4. MarkDown基础语法大全

    一.MarkDown是什么? Markdown是一种轻量级的「标记语言」,创始人为约翰·格鲁伯,用简洁的语法代替排版,目前被越来越多的知识工作者.写作爱好者.程序员或研究员广泛使用.其常用的标记符号不 ...

  5. LightOJ 1336 - Sigma Function

    原题链接 基础数论中很经典的一道题 题意 给出了σ(n)的计算公式,让你找出整数1-n中有多少对应σ(n)的值是偶数. 思路 观察σ(n)的公式发现,每一个乘项都是 (piei+1 - 1) / (p ...

  6. before和after兼容性测试

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  7. POJ1044 Date bugs

    题目来源:http://poj.org/problem?id=1044 题目大意: 与众所周知的”千年虫“类似,某些计算机上存在日期记录的bug.它们的时钟有一个年份周期,每当到达最大值时,就会自动跳 ...

  8. POJ1040 Transportation

    题目来源:http://poj.org/problem?id=1040 题目大意: 某运输公司要做一个测试.从A城市到B城市的一条运输线路中有若干个站,将所有站包括A和B在内按顺序编号为0到m.该路线 ...

  9. vue中一些常见错误

    一:在抽取路由模块时路径没有更改过来 二:跨域的问题

  10. JPA教程

    http://www.yiibai.com/jpa/jpa_criteria_api.html