\(\\\)

\(\#A\) \(Word\)


给出一个长为\(N\)的小写字母串,判断出现所有字母中最多出现次数减最少出现次数得到的答案是否是质数。

  • \(N\in [1,100]\)
  • 直接按题意开桶记录,试除法判断即可。
#include<cmath>
#include<cstdio>
#include<cctype>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define N 30
#define M 110
#define R register
using namespace std; bool v1[N],v2[N];
int to[N],now[M],p; int main(){
char c=getchar();
while(!isupper(c)) c=getchar();
while(isupper(c)){
now[++now[0]]=c-'A'+1;
v1[c-'A'+1]=1; c=getchar();
}
for(R int i=1;i<=26;++i) if(!v1[i]){puts("Failed");return 0;}
while(!isupper(c)) c=getchar();
while(isupper(c)){
int x=now[++p];
if(to[x]){if('A'+to[x]-1!=c){puts("Failed");return 0;}}
else if(v2[c-'A'+1]){puts("Failed");return 0;}
else to[x]=c-'A'+1;
v2[c-'A'+1]=1; c=getchar();
}
while(!isupper(c)) c=getchar();
while(isupper(c)){
putchar((char)'A'+to[c-'A'+1]-1);
c=getchar();
}
return 0;
}

\(\\\)

\(\#B\) \(Matches\)


已知用火柴棒拼出每个数字所需要的数量,加号和等号各需要两根,求恰好用掉\(N\)根火柴棒构成等式\(A+B=C\)的数量,其中数字不能有前导零,当\(A\not=B\)时交换位置视作两个等式。

  • \(N\in [0,24]\)
  • 用暴力跑一跑,发现最大的数据范围能做到的等式数字大小不会超过\(1000\)。
  • 于是预处理前\(1000\)个数每个数所需个数,\(N^2\)暴力枚举判断即可。
#include<cmath>
#include<cstdio>
#include<cctype>
#include<cstring>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#define R register
using namespace std; const int cost[10]={6,2,5,5,4,5,6,3,7,6}; int n,cnt,f[2500]={6}; inline void calc(int x){
int tmp=x,res=0;
while(tmp){
res+=cost[tmp%10];
tmp/=10;
}
f[x]=res;
} int main(){
scanf("%d",&n); n-=4;
for(R int i=1;i<=2300;++i) calc(i);
for(R int i=0;i<=1111;++i)
for(R int j=0;j<=1111;++j)
if(f[i]+f[j]+f[i+j]==n) ++cnt;
printf("%d\n",cnt);
return 0;
}

\(\\\)

\(\#C\) \(Massage\)


给出一个\(N\times M\)的矩阵,选则两条从\((1,1)\)到\((N,M)\)的路径,使得两条路径上的权值和最大,注意每个格点的权值只能被计入答案一次。

  • \(N,M\in [0,50]\)
  • 状态显然跟步数以及两条路径的当前终点\((x_1,y_1)(x_2,y_2)\)有关,注意到两个终点的横纵坐标之和是固定的,因为起点为\((1,1)\),所以有\(x_1+y_1=x_2+y_2=2+\)当前步数。

  • 精简状态,设\(f[i][j][k]\)表示当前两节点横纵坐标之和(即\(2+\)当前步数)为\(i\),第一条路径终点为\((j,i-j)\),第二条路径终点为\((k,i-k)\)的最大路径权值和。有显然的初始化\(f[2][1][1]=val[1][1]\)。

  • 考虑对于已知状态\(f[i][j][k]\)的转移,根据下一步两条路径的行动方向讨论,有\(2\times 2=4\)种情况:

    • 两个都向下:若当前两终点重合,则下一步也重合,权值只计算一次,否则分开累加答案:
    if(j==k) f[i+1][j+1][k+1]=max(f[i+1][j+1][k+1],f[i][j][k]+val[j+1][i-j]);
    else f[i+1][j+1][k+1]=max(f[i+1][j+1][k+1],f[i][j][k]+val[j+1][i-j]+val[k+1][i-k]);
    • 两个都向右:讨论同上:
    if(j==k) f[i+1][j][k]=max(f[i+1][j][k],f[i][j][k]+val[j][i+1-j]);
    else f[i+1][j][k]=max(f[i+1][j][k],f[i][j][k]+val[j][i+1-j]+val[k][i+1-k]);
    • 第一个向右,第二个向下:若\(j=k+1\),则代表下一步重合,权值只计算一次,否则分开累加:
    if(k==j-1) f[i+1][j][k+1]=max(f[i+1][j][k+1],f[i][j][k]+val[j][i+1-j]);
    else f[i+1][j][k+1]=max(f[i+1][j][k+1],f[i][j][k]+val[j][i+1-j]+val[k+1][i-k]);
    • 第一个向下,第二个向右:讨论同上,条件改为\(k=j+1\):
    if(j==k-1) f[i+1][j+1][k]=max(f[i+1][j+1][k],f[i][j][k]+val[k][i+1-k]);
    else f[i+1][j+1][k]=max(f[i+1][j+1][k],f[i][j][k]+val[k][i+1-k]+val[j+1][i-j]);
  • 答案即为\(f[N+M][N][N]\)。

#include<cmath>
#include<cstdio>
#include<cctype>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define N 120
#define R register
#define gc getchar
using namespace std; int n,m,val[N][N],f[N<<1][N][N]; inline int rd(){
int x=0; bool f=0; char c=gc();
while(!isdigit(c)){if(c=='-')f=1;c=gc();}
while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=gc();}
return f?-x:x;
} int main(){
n=rd(); m=rd();
for(R int i=1;i<=n;++i)
for(R int j=1;j<=m;++j) val[i][j]=rd();
f[2][1][1]=val[1][1];
for(R int i=2;i<=n+m-1;++i)
for(R int j=1;j<=n;++j)
for(R int k=1;k<=n;++k){
if(j==k){
f[i+1][j][k]=max(f[i+1][j][k],f[i][j][k]+val[j][i+1-j]);
f[i+1][j+1][k+1]=max(f[i+1][j+1][k+1],f[i][j][k]+val[j+1][i-j]);
}
else{
f[i+1][j][k]=max(f[i+1][j][k],f[i][j][k]+val[j][i+1-j]+val[k][i+1-k]);
f[i+1][j+1][k+1]=max(f[i+1][j+1][k+1],f[i][j][k]+val[j+1][i-j]+val[k+1][i-k]);
}
if(j==k-1) f[i+1][j+1][k]=max(f[i+1][j+1][k],f[i][j][k]+val[k][i+1-k]);
else f[i+1][j+1][k]=max(f[i+1][j+1][k],f[i][j][k]+val[k][i+1-k]+val[j+1][i-j]);
if(k==j-1) f[i+1][j][k+1]=max(f[i+1][j][k+1],f[i][j][k]+val[j][i+1-j]);
else f[i+1][j][k+1]=max(f[i+1][j][k+1],f[i][j][k]+val[j][i+1-j]+val[k+1][i-k]);
}
printf("%d\n",f[n+m][n][n]);
return 0;
}

\(\\\)

\(\#D\) \(Twostack\)


试通过\(2\)个栈\(S_1\)和\(S_2\),借助以下\(4\)种操作实现将输入的一个\(N\)的排列升序排序。

  • 操作\(a\):如果输入序列不为空,将第一个元素压入栈\(S_1\)
  • 操作\(b\):如果栈\(S_1\)不为空,将\(S_1\)栈顶元素弹出至输出序列
  • 操作\(c\):如果输入序列不为空,将第一个元素压入栈\(S_2\)
  • 操作\(d\):如果栈\(S_2\)不为空,将\(S_2\)栈顶元素弹出至输出序列

如果输入的排列不是“可双栈排序排列”,输出\(0\)。否则输出字典序最小的操作序列。

  • \(N\in [0,1000]\)
  • 当两个数不能连续进入同一个栈,首先需要满足前面的数小于后面的数,其次,前面的数不能在后面的数进栈之前弹出。当一个数可以弹栈,证明小于它的数字已经全部弹出,所以我们可以这样判断:

    • 预处理出每一个数的后缀\(min\)。
    • \(N^2\)枚举两个数\(a,b\)(\(a\)在\(b\)之前出现):若\(a<b\)且\(a>min_b\)则证明两者不能进入同一个栈。
  • 如何判断是否有合法操作序列呢?注意到若合法这些点应该能通过互斥关系至多分成两类,所以不妨在不能进入同一个栈的两个点间连边,进行二分图染色,若该图是二分图则证明有合法操作关系。
  • 因为要最小字典序答案,所以第一个数必定进\(S_1\)栈,注意到可能这张图不连通,所以将每次第一个遇到的点都染成黑色,代表进入\(S_1\)栈。
  • 然后就可以模拟进出栈的过程了:每到一个点就按照染色入栈,然后检查是否有需要弹栈的数字,因为我们确定了输入序列为一个排列,所以直接通过栈顶权值判断。
  • 但注意不能直接在插入之后把所有能弹出的数字都弹出,因为可能会存在先让数字进入第一个栈再弹出第二个栈的更优解法,所以操作变为:若插入\(S_2\),则能弹则弹;若插入\(S_1\),则先将一号栈该弹出的弹出(注意可能会附加二号栈的弹出),入栈,再将二号栈该弹出的弹出。
#include<cmath>
#include<cstdio>
#include<cctype>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define N 1010
#define R register
#define gc getchar
#define top1 stk1[0]
#define top2 stk2[0]
using namespace std; int num[N],mn[N],to[N],stk1[N],stk2[N]; int n,m,tot,hd[N];
struct edge{int to,nxt;}e[N*N];
inline void add(int u,int v){
e[++tot].to=v; e[tot].nxt=hd[u]; hd[u]=tot;
} inline int rd(){
int x=0; bool f=0; char c=gc();
while(!isdigit(c)){if(c=='-')f=1;c=gc();}
while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=gc();}
return f?-x:x;
} inline bool dfs(int u,int tmp){
to[u]=tmp;
for(R int i=hd[u],v;i;i=e[i].nxt)
if(!to[v=e[i].to]){if(dfs(v,3-tmp))return 1;}
else if(to[v]==tmp) return 1;
return 0;
} int main(){
n=rd();
for(R int i=1;i<=n;++i) num[i]=rd();
mn[n]=num[n];
for(R int i=n-1;i>=1;--i) mn[i]=min(mn[i+1],num[i]);
for(R int i=1;i<n;++i)
for(R int j=i+1;j<=n;++j)
if(num[i]<num[j]&&num[i]>mn[j]){add(i,j);add(j,i);}
for(R int i=1;i<=n;++i)
if(!to[i]) if(dfs(i,1)){putchar('0');return 0;};
m=1;
for(R int i=1;i<=n;++i){
if(to[i]==1){putchar('a'); putchar(' '); stk1[++top1]=num[i];}
else{putchar('c'); putchar(' '); stk2[++top2]=num[i];}
while(stk1[top1]==m||stk2[top2]==m){
if(stk1[top1]==m){putchar('b');putchar(' ');--top1;}
else{putchar('d');putchar(' ');--top2;} ++m;
}
}
return 0;
}

[ NOIP 2008 ] TG的更多相关文章

  1. NOIP 2008提高组第三题题解by rLq

    啊啊啊啊啊啊今天已经星期三了吗 那么,来一波题解吧 本题地址http://www.luogu.org/problem/show?pid=1006 传纸条 题目描述 小渊和小轩是好朋友也是同班同学,他们 ...

  2. Luogu 1006 传纸条 / NOIP 2008 传纸条(动态规划)

    Luogu 1006 传纸条 / NOIP 2008 传纸条(动态规划) Description 小渊和小轩是好朋友也是同班同学,他们在一起总有谈不完的话题.一次素质拓展活动中,班上同学安排做成一个m ...

  3. noip 2008 传纸条

    题目描述 小渊和小轩是好朋友也是同班同学,他们在一起总有谈不完的话题.一次素质拓展活动中,班上同学安排做成一个m行n列的矩阵,而小渊和小轩被安排在矩阵对角线的两端,因此,他们就无法直接交谈了.幸运的是 ...

  4. 历年真题 未完成(Noip 2008 - Noip 2017)

    Noip 2008 :全部 Noip 2009 :全部 Noip 2010 :AK Noip 2011 :AK Noip 2012 : Vigenère 密码,国王游戏,开车旅行 Noip 2013 ...

  5. TYVJ 1011 NOIP 2008&&NOIP 2000 传纸条&&方格取数 Label:多线程dp

    做题记录:2016-08-15 15:47:07 背景 NOIP2008复赛提高组第三题 描述 小渊和小轩是好朋友也是同班同学,他们在一起总有谈不完的话题.一次素质拓展活动中,班上同学安排做成一个m行 ...

  6. [ NOIP 2014 ] TG

    \(\\\) \(Day\ 1\) \(\\\) \(\#\ A\) \(Rps\) 定义五种方案的石头剪刀布游戏,两人共进行\(N\)局游戏,已知两人各自的循环节和具体方案,胜者得\(1\)分,败者 ...

  7. NOIP 2008 双栈排序

    题目描述 Tom最近在研究一个有趣的排序问题.如图所示,通过2个栈S1和S2,Tom希望借助以下4种操作实现将输入序列升序排序. 操作a 如果输入序列不为空,将第一个元素压入栈S1 操作b 如果栈S1 ...

  8. NOIP 2008 传纸条 NOIP 2000 方块取数 多线程DP

    思路都是一样,建立一个四维dp然后跑一发就完了 当然,也可以像我这么帅的人,降成三维再傻傻的跑一发啦啦啦~ #include<iostream> #include<stdio.h&g ...

  9. NOIP 2008 立体图 (字符串+模拟)

    立体图 时间限制: 1 Sec  内存限制: 50 MB提交: 2  解决: 0[提交][状态][讨论版][命题人:外部导入] 题目描述 小渊是个聪明的孩子,他经常会给周围的小朋友们讲些自己认为有趣的 ...

随机推荐

  1. Java中list集合ArrayList 中contains包含的使用

    Java中list集合ArrayList 中contains包含的使用 https://blog.csdn.net/qq_38556611/article/details/78774690

  2. hibernate的QBC查询之Criteria用法

    //return (DeliverCost) super.getSession().createCriteria(getMyClass()).add(Restrictions.eq("isd ...

  3. 闸门机制(Gate Mechanism)

    本系列文章由 @yhl_leo 出品,转载请注明出处. 文章链接: http://blog.csdn.net/yhl_leo/article/details/51728107 神经网络中常说的闸门机制 ...

  4. 写给对<meta content="IE=edge,chrome=1" http-equiv="X-UA-Compatible">迷惑不解的小伙伴

    1.X-UA-Compatible X-UA-Compatible是自从IE8新加的一个设置,对于IE8以下的浏览器是不识别的. 通过在meta中设置X-UA-Compatible的值,可以指定网页的 ...

  5. 洛谷—— P1825 [USACO11OPEN]玉米田迷宫Corn Maze

    https://www.luogu.org/problem/show?pid=1825 题目描述 This past fall, Farmer John took the cows to visit ...

  6. gradle: 修改gradle-xx-bin.zip下载地址

    进入gradle/wrapper/目录,修改gradle-wrapper.properties文件, 将distributionUrl修改为自己的下载地址即可. 另外修改gradle reposito ...

  7. DICOM:dcm4che工具包怎样压缩dcm文件探讨(续篇)

    背景 前段时间博文DICOM:dcm4che工具包怎样压缩dcm文件探讨(前篇)提到了一个问题:"利用dcm4che工具包中的dcm2dcm来进行dcm文件的压缩和加压缩.即改变dcm文件里 ...

  8. PHP array_merge_recursive()

    定义和用法 array_merge_recursive() 函数与 array_merge()函数 一样,将一个或多个数组的元素的合并起来,一个数组中的值附加在前一个数组的后面.并返回作为结果的数组. ...

  9. SQL 2012中文乱码

    MS SQL插入汉字的时候.常常会遇到部分汉字变成了乱码问号了, 所以在安装数据库或者在创建表的时候须要注意一下几点: 1.保存汉字的字段要用NVARCHAR.NCHAR.NTEXT等.插入的时候要用 ...

  10. NoSql的易扩展性

    NoSql现在很火很时髦,大家言必称NoSql,仿佛关系型数据库已成陈旧落后的代名词. 但依我看,真正理解NoSql的还不多,在实际项目中用过的应该就更少了. 我也还不理解,更没怎么应用过,所以现在要 ...