点此进入比赛

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

排名: \(Rank\ 16\)

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

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

第一眼看完毫无想法。

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

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

代码如下:

#include<bits/stdc++.h>
#define max(x,y) ((x)>(y)?(x):(y))
#define min(x,y) ((x)<(y)?(x):(y))
#define uint unsigned int
#define LL long long
#define ull unsigned long long
#define swap(x,y) (x^=y,y^=x,x^=y)
#define abs(x) ((x)<0?-(x):(x))
#define INF 1e9
#define Inc(x,y) ((x+=(y))>=MOD&&(x-=MOD))
#define ten(x) (((x)<<3)+((x)<<1))
#define N 10000
using namespace std;
int n=0,num[N+5];
class FIO
{
private:
#define Fsize 100000
#define tc() (FinNow==FinEnd&&(FinEnd=(FinNow=Fin)+fread(Fin,1,Fsize,stdin),FinNow==FinEnd)?EOF:*FinNow++)
#define pc(ch) (FoutSize<Fsize?Fout[FoutSize++]=ch:(fwrite(Fout,1,FoutSize,stdout),Fout[(FoutSize=0)++]=ch))
int f,FoutSize,OutputTop;char ch,Fin[Fsize],*FinNow,*FinEnd,Fout[Fsize],OutputStack[Fsize];
public:
FIO() {FinNow=FinEnd=Fin;}
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;}
inline bool read_digit(int &x) {while(!isdigit(x=tc())) if(!~x) return false;return x&=15,true;}
inline void read_char(char &x) {while(isspace(x=tc()));}
inline void read_string(string &x) {x="";while(isspace(ch=tc()));while(x+=ch,!isspace(ch=tc())) if(!~ch) return;}
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;}
inline void write_char(char x) {pc(x);}
inline void write_string(string x) {register int i,len=x.length();for(i=0;i<len;++i) pc(x[i]);}
inline void end() {fwrite(Fout,1,FoutSize,stdout);}
}F;
inline void Solve(int x,int v)//x表示当前处理到的位数,v表示剩余的数位和
{
if(num[x]>=v) return (void)(F.write_char(v+48),num[x]-=v);//如果该位数字≥v,就输出v,并将该位数字减去v
Solve(x-1,v-num[x]),F.write_char(num[x]+48),num[x]=0;//如果该位数字<v,就处理更高的一位,然后输出该位数字(注意,这顺序不能反),然后将该位数字赋值为0
}
int main()
{
register int i,x,sum=0;
while(F.read_digit(x)) sum+=(num[++n]=x);//用sum统计数位之和
if(sum%3) return puts("-1"),0;//如果sum不能被3整除,说明无解
for(i=1;i<=3;++i) Solve(n,sum/3),F.write_char(' ');//输出答案
return F.end(),0;
}

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

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

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

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

#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})\)。

代码如下:

#include<bits/stdc++.h>
#define max(x,y) ((x)>(y)?(x):(y))
#define min(x,y) ((x)<(y)?(x):(y))
#define uint unsigned int
#define LL long long
#define ull unsigned long long
#define swap(x,y) (x^=y,y^=x,x^=y)
#define abs(x) ((x)<0?-(x):(x))
#define INF 1e9
#define Inc(x,y) ((x+=(y))>=MOD&&(x-=MOD))
#define ten(x) (((x)<<3)+((x)<<1))
#define N 100
#define K 5
#define AddBalls(y,z) (s[++n]=Balls(y,z),lst[n]=End[y],End[y]=n)
#define NeedBall(x) ((x)<k?k-(x):0)//求出还需多少个球
using namespace std;
int n,k,lst[N+5],End[N+5];
struct Balls//记录连续一段颜色相同的求的信息
{
int col,num;//col记录颜色,num记录数量
Balls(int x=0,int y=0):col(x),num(y){}
}s[N+5];
class FIO
{
private:
#define Fsize 100000
#define tc() (FinNow==FinEnd&&(FinEnd=(FinNow=Fin)+fread(Fin,1,Fsize,stdin),FinNow==FinEnd)?EOF:*FinNow++)
#define pc(ch) (FoutSize<Fsize?Fout[FoutSize++]=ch:(fwrite(Fout,1,FoutSize,stdout),Fout[(FoutSize=0)++]=ch))
int f,FoutSize,OutputTop;char ch,Fin[Fsize],*FinNow,*FinEnd,Fout[Fsize],OutputStack[Fsize];
public:
FIO() {FinNow=FinEnd=Fin;}
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;}
inline void read_char(char &x) {while(isspace(x=tc()));}
inline void read_string(string &x) {x="";while(isspace(ch=tc()));while(x+=ch,!isspace(ch=tc())) if(!~ch) return;}
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;}
inline void write_char(char x) {pc(x);}
inline void write_string(string x) {register int i,len=x.length();for(i=0;i<len;++i) pc(x[i]);}
inline void end() {fwrite(Fout,1,FoutSize,stdout);}
}F;
class Class_DP
{
private:
int f[N+5][N+5][K+5];//f[l][r][v]表示在编号为r的珠子右边有v个与r号珠子同色的珠子时,要把[l,r]区间内的珠子消完所需要增加的最少珠子数
public:
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,方便记忆化
inline int GetAns(int l,int r,int v)//记忆化搜索
{
if(~f[l][r][v]) return f[l][r][v];//如果已经求解过,返回求出的答案
register int i,t;
for(f[l][r][v]=GetAns(l,r-1,0)+NeedBall(s[r].num+v),i=l;i<r;++i)
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);//状态转移
return f[l][r][v];
}
}DP;
int main()
{
register int i,nn,x,y,z=1;
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);
return AddBalls(y,z),DP.Init(),F.write(DP.GetAns(1,n,0)),F.end(),0;//输出答案
}

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

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

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

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

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

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

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

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

#include<bits/stdc++.h>
#define max(x,y) ((x)>(y)?(x):(y))
#define min(x,y) ((x)<(y)?(x):(y))
#define uint unsigned int
#define LL long long
#define ull unsigned long long
#define swap(x,y) (x^=y,y^=x,x^=y)
#define abs(x) ((x)<0?-(x):(x))
#define INF 1e9
#define Inc(x,y) ((x+=(y))>=MOD&&(x-=MOD))
#define ten(x) (((x)<<3)+((x)<<1))
#define N 1000000
using namespace std;
string st;
class FIO
{
private:
#define Fsize 100000
#define tc() (FinNow==FinEnd&&(FinEnd=(FinNow=Fin)+fread(Fin,1,Fsize,stdin),FinNow==FinEnd)?EOF:*FinNow++)
#define pc(ch) (FoutSize<Fsize?Fout[FoutSize++]=ch:(fwrite(Fout,1,FoutSize,stdout),Fout[(FoutSize=0)++]=ch))
int f,FoutSize,OutputTop;char ch,Fin[Fsize],*FinNow,*FinEnd,Fout[Fsize],OutputStack[Fsize];
public:
FIO() {FinNow=FinEnd=Fin;}
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;}
inline void read_char(char &x) {while(isspace(x=tc()));}
inline void read_string(string &x) {x="";while(isspace(ch=tc()));while(x+=ch,!isspace(ch=tc())) if(!~ch) return;}
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;}
inline void write_char(char x) {pc(x);}
inline void write_string(string x) {register int i,len=x.length();for(i=0;i<len;++i) pc(x[i]);}
inline void end() {fwrite(Fout,1,FoutSize,stdout);}
}F;
class Class_HashSolver//用字符串哈希求解答案
{
private:
struct Hash//双哈希
{
ull fir,sec;
Hash(ull x=0,ull y=0):fir(x),sec(y){}
}seed,s[N+5],t[N+5];
inline friend Hash operator + (Hash x,Hash y) {return Hash(x.fir+y.fir,x.sec+y.sec);}//重载加法
inline friend Hash operator - (Hash x,Hash y) {return Hash(x.fir-y.fir,x.sec-y.sec);}//重载减法
inline friend Hash operator * (Hash x,Hash y) {return Hash(x.fir*y.fir,x.sec*y.sec);}//重载乘法
inline friend bool operator == (Hash x,Hash y) {return !(x.fir^y.fir||x.sec^y.sec);}//重载等于号
public:
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;}//初始化
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);}//对字符串进行哈希
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]));}//比较两段区间内的字符串是否相同
inline int GetAns(int l,int r)//求解[l,r]区间内的答案
{
if(l>r) return 0;
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
return 1;//否则,这整个字符串对答案造成的贡献为1
}
}HashSolver;
int main()
{
register int T;F.read(T);
while(T--) F.read_string(st),HashSolver.Init(st),F.write(HashSolver.GetAns(1,st.length())),F.write_char('\n');
return F.end(),0;
}

【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. -bash: ./bak_1.py: /usr/bin/python^M: bad interpreter: 没有那个文件或目录

    在Windows的PyCharm中编写了一个Python文件,然后上传至CentOS中,已经添加执行权限,但是仍然会报如下的错误: 代码如下: #!/usr/bin/python # -*- codi ...

  2. Docker 启动配置和远程访问

    1. 添加Docker 启动时的配置:   vi /etc/default/docker 添加:   DOCKER_OPTS=" --label name=dockerServer1 -H ...

  3. cf780E(dfs)

    题目链接: http://codeforces.com/problemset/problem/780/E 题意: 给出一个 n 个点 m 条边的图, 有 k 个人, 初始位置可以为任意位置, 每个人最 ...

  4. 一个APK反编译利器Apktool

    一个APK反编译利器Apktool   APK 本地化 [http://www.andmoto.com/viewthread.php?tid=3873]   说起APK的汉化,目前大部分教程都是让用H ...

  5. 在Python中使用asyncio进行异步编程

    对于来自JavaScript编码者来说,异步编程不是什么新东西,但对于Python开发者来说,async函数和future(类似JS的promise)可不是那么容易能理解的. Concurrency ...

  6. 小程序组件的继承 - behavior

    1.目录结构 demo-one 和 demo-two 一起公用一些属性 和 方法 存在demo-beh.js中 需要像模块一样导出 2.调用的方法: // components/demo-class/ ...

  7. PHP学习 文件操作函数的应用--简单网络留言模板

    <?php /** 网络留言板模式 主要运用到的函数有 fopen fclose flock fwrite fread explode list */ ?> <meta http-e ...

  8. @Import @bean,@Conditional @ConfigurationProperties @EnableConfigurationProperties 注解使用

    一分钟学会spring注解之@Import注解http://blog.51cto.com/4247649/2118354 @Autowired与@Resource 注解的使用 https://www. ...

  9. JD孔_20160920

    1. 2. 3.

  10. 018 4Sum 四个数的和

    给定一个含有 n 个整数的数组 S,数列 S 中是否存在元素 a,b,c 和 d 使 a + b + c + d = target ?请在数组中找出所有满足各元素相加等于特定值的不重复组合.注意:解决 ...