\(\\\)

\(\#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. 【Codeforces 992B】Nastya Studies Informatics

    [链接] 我是链接,点我呀:) [题意] 题意 [题解] 因为gcd(a,b)=x 所以设a = nx b = mx 又有ab/gcd(a,b)=lcm(a,b)=y 则nmx = y 即n(m*x) ...

  2. VMWare学习总结(1)——Centos7安装完毕后无法联网的解决方法

    在VmWare 上安装Centos7时,装好vmware后还是连不上网,通过查找资料原来是因为有线网卡没有激活,默认centos和redhat7都是不启用有线网卡的,要么手动开启,要么安装时直接启用! ...

  3. 程序员节QWQ

    据$lc$说,今天是程序员节QWQ 过节啦QWQ

  4. 页面加载即执行JQuery的三种方法

    [1]$(function( ){ }): $(function(){ $("#name").click(function(){ //adding your code here } ...

  5. Asm.Def谈笑风生

    ★   输入文件:asm_talk.in   输出文件:asm_talk.out简单对比时间限制:2 s   内存限制:256 MB [题目描述] “人呐都不知道,自己不可以预料,直升机刚一出圣地亚哥 ...

  6. HDU——2588 GCD

    题目大意: 求1~N中与N的最大公约数大于M的个数 思路: 这个题是不是可以想到暴力枚举??对于每一组数据枚举与他的最大公约数大于m的数的个数. 是,这种做法没错误,但是保准你T成狗.... 我们至少 ...

  7. 武大OJ 574. K-th smallest

    Description Give you a number S of length n,you can choose a position and remove the number on it.Af ...

  8. HDU 1166敌兵布阵

    敌兵布阵 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submis ...

  9. 多Tabs的横向滚动插件(支持Zepto和jQuery)

    一. 效果图 二. 功能介绍 1. 支持横向移动 2. 支持点击Tab后该Tab居中 3. 拉到最左边和最右边后依然可以拉动,只是tabs的移动距离变小. 三. 使用说明 1. 在你的html中添加T ...

  10. iOS8開始默认语言有变化

    [问题] 測试组发现APP在iOS8及以上系统设备上,语言设置为我们不支持的小语种时.APP没有使用默认的英文,而是选择了上一次设置的语言. [分析] 经过研究发现,在iOS8系统開始,在设备语言设置 ...