首页 > 技术文章 > noip2008题解

zyx45889 2016-11-17 19:28 原文

背景

笨小猴的词汇量很小,所以每次做英语选择题的时候都很头疼。但是他找到了一种方法,经试验证明,用这种方法去选择选项的时候选对的几率非常大!

描述

这种方法的具体描述如下:假设maxn是单词中出现次数最多的字母的出现次数,minn是单词中出现次数最少的字母的出现次数,如果maxn-minn是一个质数,那么笨小猴就认为这是个Lucky Word,这样的单词很可能就是正确的答案。

格式

输入格式

输入只有一行,是一个单词,其中只可能出现小写字母,并且长度小于100。

输出格式

输出共两行,第一行是一个字符串,假设输入的的单词是Lucky Word,那么输出“Lucky Word”,否则输出“No Answer”;

第二行是一个整数,如果输入单词是Lucky Word,输出maxn-minn的值,否则输出0。

样例1

样例输入1[复制]

 
error

样例输出1[复制]

 
Lucky Word
2

样例2

样例输入2[复制]

 
olymipic

样例输出2[复制]

 
No Answer
0

限制

各个测试点1s

提示

【输入输出样例1解释】
单词error中出现最多的字母r出现了3次,出现次数最少的字母出现了1次,3-1=2,2是质数。

【输入输出样例2解释】
单词olymipic中出现最多的字母i出现了2次,出现次数最少的字母出现了1次,2-1=1,1不是质数。

模拟找出最多字母最少字母即可

vijos1495

 1 #include<stdio.h>
 2 #include<string.h>
 3 int zhi(int o)
 4 {
 5     int i,p=0;
 6     for(i=2;i<(o/2);i++)
 7     if(o%i==0)p=1;
 8     if(o==0||o==1)p=1;
 9     return p;
10 }
11 int main()
12 {
13     char s[100];
14     int l,i,a[100]={0},m=0,n=0;
15     scanf("%s",s);
16     for(i=0;i<=strlen(s)-1;i++)
17       for(l=0;l<=strlen(s)-1;l++)
18         if(s[i]==s[l])a[i]++;
19     n=a[1];
20     for(i=0;i<=strlen(s)-1;i++)
21     {
22       if(a[i]<n)n=a[i];
23       if(a[i]>m)m=a[i];
24     }
25     if(zhi(m-n)==0)printf("Lucky Word\n%d",m-n);
26     else printf("No Answer\n0");
27     return 0;
28 }

描述

给你n根火柴棍,你可以拼出多少个形如“A+B=C”的等式?等式中的A、B、C是用火柴棍拼出的整数(若该数非零,则最高位不能是0)。用火柴棍拼数字0-9的拼法如图所示:

注意:

1. 加号与等号各自需要两根火柴棍

2. 如果A≠B,则A+B=C与B+A=C视为不同的等式(A、B、C>=0)

3. n根火柴棍必须全部用上

格式

输入格式

输入共一行,有一个整数n(n<=24)。

输出格式

输出共一行,表示能拼成的不同等式的数目。

样例1

样例输入1[复制]

 
14

样例输出1[复制]

 
2

样例2

样例输入2[复制]

 
18

样例输出2[复制]

 
9

限制

1s

提示

【输入输出样例1解释】

2个等式为0+1=1和1+0=1。

【输入输出样例2解释】

9个等式为:

0+4=4

0+11=11

1+10=11

2+2=4

2+7=9

4+0=4

7+2=9

10+1=11

11+0=11

搜索...

vjos1496

 1 #include<stdio.h>
 2 int main( )
 3 {
 4     int n,i,j,t,a[10],t1,i1,j1,add=0;
 5     a[0]=6;
 6     a[1]=2;
 7     a[2]=5;
 8     a[3]=5;
 9     a[4]=4;
10     a[5]=5;
11     a[6]=6;
12     a[7]=3;
13     a[8]=7;
14     a[9]=6;
15     scanf("%d",&n);
16     for(i=0;i<=2000;i++)
17      for(j=0;j<=2000;j++)
18       {
19         t=i+j;
20         if(t>=1000) t1=a[t/1000]+a[t%10]+a[t%100/10]+a[t%1000/100];
21         else if(t>=100) t1=a[t/100]+a[t%10]+a[t%100/10];
22         else if(t>=10) t1=a[t/10]+a[t%10];
23         else  t1=a[t];
24 
25          if(i>=1000) i1=a[i/1000]+a[i%10]+a[i%100/10]+a[i%1000/100];
26         else if(i>=100) i1=a[i/100]+a[i%10]+a[i%100/10];
27          else if(i>=10) i1=a[i/10]+a[i%10];
28         else  i1=a[i];
29 
30 
31          if(j>=1000) j1=a[j/1000]+a[j%10]+a[j%100/10]+a[j%1000/100];
32         else if(j>=100) j1=a[j/100]+a[j%10]+a[j%100/10];
33          else if(j>=10) j1=a[j/10]+a[j%10];
34         else  j1=a[j];
35 
36         if(t1+i1+j1+4==n) add++;
37         t1=0;i1=0;j1=0;
38        }
39        printf("%d",add);
40 
41        return 0;
42 }

描述

小渊和小轩是好朋友也是同班同学,他们在一起总有谈不完的话题。一次素质拓展活动中,班上同学安排做成一个m行n列的矩阵,而小渊和小轩被安排在矩阵对角线的两端,因此,他们就无法直接交谈了。幸运的是,他们可以通过传纸条来进行交流。纸条要经由许多同学传到对方手里,小渊坐在矩阵的左上角,坐标(1,1),小轩坐在矩阵的右下角,坐标(m,n)。从小渊传到小轩的纸条只可以向下或者向右传递,从小轩传给小渊的纸条只可以向上或者向左传递。

在活动进行中,小渊希望给小轩传递一张纸条,同时希望小轩给他回复。班里每个同学都可以帮他们传递,但只会帮他们一次,也就是说如果此人在小渊递给小轩纸条的时候帮忙,那么在小轩递给小渊的时候就不会再帮忙。反之亦然。

还有一件事情需要注意,全班每个同学愿意帮忙的好感度有高有低(注意:小渊和小轩的好心程度没有定义,输入时用0表示),可以用一个0-100的自然数来表示,数越大表示越好心。小渊和小轩希望尽可能找好心程度高的同学来帮忙传纸条,即找到来回两条传递路径,使得这两条路径上同学的好心程度只和最大。现在,请你帮助小渊和小轩找到这样的两条路径。

格式

输入格式

输入第一行有2个用空格隔开的整数m和n,表示班里有m行n列(1<=m,n<=50)。
接下来的m行是一个m*n的矩阵,矩阵中第i行j列的整数表示坐在第i行j列的学生的好心程度。每行的n个整数之间用空格隔开。

输出格式

输出共一行,包含一个整数,表示来回两条路上参与传递纸条的学生的好心程度之和的最大值。

样例1

样例输入1[复制]

 
3 3
0 3 9
2 8 5
5 7 0

样例输出1[复制]

 
34

限制

各个测试点1s

提示

【限制】
30%的数据满足:1<=m,n<=10
100%的数据满足:1<=m,n<=50

正确性稍需思考
vijos1493
 1 #include<cstdio>
 2 using namespace std;
 3 
 4 int num[55][55],answer[55][55][55][55];
 5 int max(int a,int b)
 6 {
 7     if(a>b)return a;
 8     return b;
 9 }
10 int main()
11 {
12     int n,m;
13     scanf("%d%d",&n,&m);
14     for(int i=1;i<=n;i++)
15       for(int j=1;j<=m;j++)
16         scanf("%d",&num[i][j]);
17     for(int i=1;i<=n;i++)
18      for(int j=1;j<=m;j++)
19       for(int k=1;k<=n;k++)
20        for(int l=1;l<=m;l++)
21         if((i!=k||j!=l)||(i==n&&k==n&&j==m&&l==m))
22          answer[i][j][k][l]=max(answer[i-1][j][k-1][l],max(answer[i-1][j][k][l-1],max(answer[i][j-1][k-1][l],answer[i][j-1][k][l-1])))+num[i][j]+num[k][l];
23     printf("%d",answer[n][m][n][m]);
24     return 0;
25 }

描述

Tom最近在研究一个有趣的排序问题。如图所示,通过2个栈S1和S2,Tom希望借助以下4种操作实现将输入序列升序排序。

操作a
如果输入序列不为空,将第一个元素压入栈S1
操作b
如果栈S1不为空,将S1栈顶元素弹出至输出序列
操作c
如果输入序列不为空,将第一个元素压入栈S2
操作d
如果栈S2不为空,将S2栈顶元素弹出至输出序列

如果一个1~n的排列P可以通过一系列操作使得输出序列为1,2,…,(n-1),n,Tom就称P是一个“可双栈排序排列”。例如(1,3,2,4)就是一个“可双栈排序序列”,而(2,3,4,1)不是。

将(1,3,2,4)排序的操作序列:<a,c,c,b,a,d,d,b>

当然,这样的操作序列有可能有几个,对于上例(1,3,2,4),<a,c,c,b,a,d,d,b>是另外一个可行的操作序列。

Tom希望知道其中字典序最小的操作序列是什么。

格式

输入格式

第一行是一个整数n。

第二行有n个用空格隔开的正整数,构成一个1~n的排列。

输出格式

输出文件共一行,如果输入的排列不是“可双栈排序排列”,输出数字0;
否则输出字典序最小的操作序列,每两个操作之间用空格隔开,行尾没有空格。

样例1

样例输入1[复制]

 
4
1 3 2 4

样例输出1[复制]

 
a b a a b b a b

限制

1s

提示

30%的数据满足: n<=10
50%的数据满足: n<=50
100%的数据满足: n<=1000

我总觉得我是在新浪上面写过题解的,让我再写一遍我就觉得憋屈...
考虑对于单栈,若存在存在k,满足i<j<k,使得a[k]<a[i]<a[j],那么排序不成立
对于双栈,这样的i,j必须分开,从而可以建立图
若图为二分图,可行,写个栈处理输出
否则,不可双栈排序
vijos1605
  1 #include<iostream>
  2 #include<stdio.h>
  3 #include<cstdlib>
  4 #include<string.h>
  5 #include<algorithm>
  6 #define N 1005
  7 using namespace std;
  8 int n,number[N];
  9 int beg[N];
 10 int cnt;
 11 int nowmin[N];
 12 int mark[N];
 13 int flag[N];
 14 
 15 class Stack
 16 {
 17 private:
 18     int rear;
 19     int stack[N];
 20 public:
 21     Stack()
 22     {
 23         rear=-1;
 24     }
 25     int Destack()
 26     {
 27         int x=stack[rear];
 28         rear--;
 29         return x;
 30     }
 31     void Enstack(int x)
 32     {
 33         rear++;
 34         stack[rear]=x;
 35     }
 36     int Getrear()
 37     {
 38         return stack[rear];
 39     }
 40     int Getsize()
 41     {
 42         return rear;
 43     }
 44 }s[2];
 45 
 46 struct edge
 47 {
 48     int b,next;
 49 }E[N];
 50 
 51 void addedge(int a,int b)
 52 {
 53     E[cnt].b=b;
 54     E[cnt].next=beg[a];
 55     beg[a]=cnt;
 56     cnt++;
 57     E[cnt].b=a;
 58     E[cnt].next=beg[b];
 59     beg[b]=cnt;
 60     cnt++;
 61 }
 62 
 63 int DFS(int now,int deep)
 64 {
 65     if(flag[now]!=-1&&flag[now]!=deep%2)
 66      return 0;
 67     flag[now]=deep%2;
 68     for(int i=beg[now];i!=-1;i=E[i].next)
 69     {
 70          if(flag[E[i].b]==(deep+1)%2)
 71           continue;
 72          if(DFS(E[i].b,deep+1)==0)
 73           return 0;
 74     }
 75     return 1;
 76 }
 77 
 78 int main()
 79 {
 80     memset(beg,-1,sizeof(beg));
 81     scanf("%d",&n);
 82     for(int i=0;i<n;i++)
 83      scanf("%d",&number[i]);
 84     nowmin[n-1]=number[n-1];
 85     for(int i=n-2;i>=0;i--)
 86      nowmin[i]=min(nowmin[i+1],number[i]);
 87     for(int i=0;i<n-1;i++)
 88      for(int j=i+1;j<n-1;j++)
 89       if(nowmin[j+1]<number[i]&&number[i]<number[j])
 90        addedge(i,j);
 91     memset(mark,-1,sizeof(mark));
 92     memset(flag,-1,sizeof(flag));
 93     for(int i=0;i<n;i++)
 94      if(mark[i]==-1)
 95      {
 96          if(DFS(i,0)==0)
 97          {
 98              printf("0\n");
 99              return 0;
100          }
101          for(int i=0;i<n;i++)
102           if(flag[i]!=-1)
103            mark[i]=flag[i];
104          memset(flag,-1,sizeof(flag));
105      }
106     int now=1;
107     for(int i=0;i<n;i++)
108     {
109         while(1)
110         {
111             int mar=0;
112             if(s[0].Getsize()!=-1&&s[0].Getrear()==now)
113             {
114                 s[0].Destack();
115                 now++;
116                 printf("b ");
117                 mar=1;
118             }
119             if(s[1].Getsize()!=-1&&s[1].Getrear()==now)
120             {
121                 s[1].Destack();
122                 now++;
123                 printf("d ");
124                 mar=1;
125             }
126             if(mar==0)
127              break;
128         }
129         s[mark[i]].Enstack(number[i]);
130         if(mark[i]==0)
131          printf("a ");
132         else printf("c ");
133     }
134     while(1)
135     {
136         int mar=0;
137         if(s[0].Getsize()!=-1&&s[0].Getrear()==now)
138         {
139             s[0].Destack();
140             now++;
141             printf("b ");
142             mar=1;
143         }
144         if(s[1].Getsize()!=-1&&s[1].Getrear()==now)
145         {
146             s[1].Destack();
147             now++;
148             printf("d ");
149             mar=1;
150         }
151         if(mar==0)
152          break;
153     }
154     return 0;
155 }

 

推荐阅读