2017_02_25周末信竞总结(上)——NOIP2008

来源:互联网 发布:ipad mini2软件下载 编辑:程序博客网 时间:2024/05/18 23:12

1. 笨小猴

(word.pas/c/cpp)
【问题描述】
笨小猴的词汇量很小,所以每次做英语选择题的时候都很头痛。但是他找到了一种方法,经试验证明,用这种方法去选择选项的时候选对的几率非常大!
这种方法的具体描述如下:假设maxn是单词中出现次数最多的字母的出现次数,minn是单词中出现次数最少的字母的出现次数,如果maxn-minn是一个质数,那么笨小猴就认为这是个Lucky Word,这样的单词很可能就是正确的答案。
【输入】
输入文件word.in只有一行,是一个单词,其中只可能出现小写字母,并且长度小于100。
【输出】
输出文件word.out共两行,第一行是一个字符串,假设输入的的单词是Lucky Word,那么输出“Lucky Word”,否则输出“No Answer”;
第二行是一个整数,如果输入单词是Lucky Word,输出maxn-minn的值,否则输出0。
【输入输出样例1】
word.in: error
word.out:Lucky Word 2
【输入输出样例1解释】
单词error中出现最多的字母r出现了3次,出现次数最少的字母出现了1次,3-1=2,2是质数。


这道题好似一道大水题(水的一逼)
对于此题,只用桶排加就能够轻松解决,在这里就不多说,献上如雷的代码(十分不清真)

#include<cstdio>#include<cstring>#include<iostream>using namespace std;int bus[30],mi=(1<<30),ma,n,m;char a[200];int main(){    freopen("word.in","r",stdin);    freopen("word.out","w",stdout);    scanf("%s",a);    n=strlen(a);    for(int i=0;i<n;i++)        bus[a[i]-'a']++;    for(int i=0;i<29;i++)    {        if(!bus[i])continue;        ma=ma<bus[i]?bus[i]:ma;        mi=mi>bus[i]?bus[i]:mi;    }    m=ma-mi;    if(m==1||m==0)        printf("No Answer\n0");    else    {        for(int i=2;i*i<=m;i++)        {            if(!(m%i))            {                printf("No Answer\n0");                return 0;            }        }        printf("Lucky Word\n%d",m);    }return 0;}

2. 火棒等式

(matches.pas/c/cpp)
【问题描述】
给你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根火柴棍必须全部用上

【输入】
输入文件matches.in共一行,又一个整数n(n<=24)。
【输出】
输出文件matches.out共一行,表示能拼成的不同等式的数目。

【输入输出样例1】
matches.in :14
matches.out :2
【输入输出样例1解释】
2个等式为0+1=1和1+0=1。

【输入输出样例2】
matches.in :18
matches.out :9
【输入输出样例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

  这道题目刚开始时有点不知所措,因为在蓝本上有一道题目也是火柴,所以一开始一直在想能不能用dp来解决,但后来发现这题目十分清蒸,有着纯正的信仰(吾主在此),输入数据只有一个火柴数啊,(๑•̀ㅂ•́)و✧根本没有其他的·限制条件。。。嗯,干脆打表算了 __(:зゝ∠)__;但其实此题并不用打表就能ac啊。。。但此处需要一定的分析,就是最大能够拼出来的等式的左端最大值是多少,首先先设为四位数1000吧,然后我们发现那么等式右端至少是1000。。。明显超了啊,1000用20根火柴。。。哪里有那么多啊。。。所以就可以将其设为1000的上限,(其实可以更低)然后dfs即可(注意,此处只需要枚举等式前面的两个加数即可,然后在用其和与所剩的火柴数相比较,不需要枚举三个数,不然会超时,这也是一种剪枝技巧(后面会总结如何将一些步骤的时间复杂度降维)
#include<cstdio>#include<iostream>#include<cstring>using namespace std;int p[10]={6,2,5,5,4,5,6,3,7,6},ans,n,ma;int get(int s){    int an=0;    if(s==0)an=6;    while(s)    {        an+=p[s%10];        s/=10;    }    return an;}void dfs(int n,int s,int a){    if(s==2)    {        if(get(a)==n)ans++;        return ;    }    for(int i=0;i<=ma;i++)    {           int d=get(i);        if(d>n)continue;        dfs(n-d,s+1,a+i);    }}int main(){    //freopen("matches.in","r",stdin);    //freopen("matches.out","w",stdout);    scanf("%d",&n);        ma=720;        ans=0;        dfs(n-4,0,0);        printf("%d\n",ans);    return 0;}


这里写图片描述

0 0
原创粉丝点击