acm新手小白必看系列之(5)——枚举进阶例题精讲

acm新手小白必看系列之(5)——枚举进阶例题精讲

1.牛奶碑文(暴力枚举)
小伟暑假期间到大草原旅游,在一块石头上发现了一些有趣的碑文。碑文似乎是一个神秘古老的语言,只包括三个大写字母 C、O 和 W。尽管小伟看不懂,但是令他高兴的是,C、O、W的顺序形式构成了一句他最喜欢的奶牛单词“COW”。现在,他想知道有多少次 COW 出现在文本中。
如果 COW 内穿插了其他字符,只要 COW 字符出现在正确的顺序,小伟也不介意。甚至,他也不介意出现不同的 COW 共享一些字母。例如,CWOW 出现了 1 次 COW,CCOW 算出现了2 次 COW,CCOOWW 算出现了 8 次 COW。(看懂这个,题就出来了)
Input
第 1 行为 1 个整数 N。
第 2 行为 N 个字符的字符串,每个字符是一个 C、O 或 W。
Output
输出 COW 作为输入字符串的字串出现的次数(不一定是连续的)。
提示:答案会很大,建议用 64 位整数**(long long)**
Sample Input
6
COOWWW
Sample Output
6
Hint
对于 50% 的数据满足:N≤60。
对于 100% 的数据满足:N≤100000。
单组输入
比如ccooww
遇到C则C的个数+1,a=2;
遇到O则CO的个数加当前C的个数,b=a+a=4;
遇到W则COW的个数加当前CO的个数,c=b+b=8;

#include 
using namespace std;
int n;//单词encounter遇到
long long enc=0, enco=0, encow=0;
string cow;
int main()
{
    scanf("%d", &n);
    cin>>cow;
    for(int i=0; i<n; i++)
    {
        if(cow[i]=='C')
            enc++;
        if(cow[i]=='O')
           enco+=enc;
        if(cow[i]=='W')
            encow+=enco;
    }
    cout<<encow<<endl;
    return 0;
}

2.丑数(暴力枚举)
只有质数2,3,5,7这几个作为因子的数叫做,丑数,比如前20个丑数是(从小到大来说) 1,2,3,4,5,6,7,8,9,10,12,14,15,16,18,20,21,24和25.
Input
我们给你个n(1<=n<=5842)当输入n为0结束。
Output
输出第n个丑数。每个数一行。
Sample Input
1
2
3
4
11
Sample Output
1
2
3
4
12
思路呢我反正就知道两种大家可以都试试噢~

  • 第一种把所有的丑数都用循环列出来然后输出,所以把丑数数组打出来就ok了(会超时),还有一种叫打表也是把所有的丑数都列出来。。。具体操作,把5842所有的丑数打出来,我相信你不会真打,所以,有个窍门是——用第一个程序打印的结果然后。。。
    这个呢,当作娱乐,下面说第二种正规的方法。
  • 丑数的另一种产生方法,由最先4个最小的丑数乘以2、3、5、7产生之后的丑数,
    并且让之后产生的所有丑数按升序排列。
#include 
#define min4(a,b,c,d) min(min(a,b),min(c,d))
using namespace std;
int n,p2,p3,p5,p7,a[5850];//定义min4(a,b,c,d),找四个数中的最小值
int main()
{
    a[1]=1;
    p2=p3=p5=p7=1;
    for(int i=2; i<=5842; i++) //打表
    {
        a[i]=min4(a[p2]*2,a[p3]*3,a[p5]*5,a[p7]*7);//a[p2]、a[p3]、a[p5]、a[p7]分别为*2、*3、*5、*7的次数,
        //找出来最小值之后,判断这个最小值是分别乘过几次2,3,5,7,乘了几遍;
        if(a[i]%2==0)p2++;//如果选择的最小值a[i]是乘以了2,则*2的丑数下标位置后移一位
        if(a[i]%3==0)p3++;
        if(a[i]%5==0)p5++;
        if(a[i]%7==0)p7++;
    }
    while(cin>>n&&n)
        printf("%d\n",a[n]);
    return 0;
}

3.趣味解题(二进制枚举)
ACM程序设计大赛是大学级别最高的脑力竞赛,素来被冠以"程序设计的奥林匹克"的尊称。大赛至今已有近40年的历史,是世界范围内历史最悠久、规模最大的程序设计竞赛。比赛形式是:从各大洲区域预赛出线的参赛队伍,于指定的时间、地点参加世界级的决赛,由1个教练、3个成员组成的小组应用一台计算机解决7到13个生活中的实际问题。
现在假设你正在参加ACM程序设计大赛,这场比赛有 n 个题目,对于第 i 个题目你有 a_i 的概率AC掉它,如果你不会呢,那么这时候队友的作用就体现出来啦,队友甲有 b_i 的概率AC掉它, 队友乙有 c_i 的概率AC掉它,那么现在教练想知道你们队伍做出 x 个题目的概率。
Input
输入一个正整数T(T<=100),表示有T组数据,对于每组数据首先输入一个 n (7<=n<=13),表示有 n 个题目,接下来输入三行,
第一行输入 n 个数a_i,第二行输入 n 个数b_i,第三行输入 n 个数c_i, 其中 a_i, b_i, c_i 的意义如题,最后输入一个 x 表示教练想要知道你们队伍做出的题目数(x>=0)。
Output
输出一行表示结果,保留4位小数
Sample Input
2
7
0.1 0.2 0.3 0.4 0.5 0.6 0.7
0.2 0.3 0.4 0.5 0.6 0.7 0.8
0.3 0.4 0.5 0.6 0.7 0.8 0.9
1
7
0.1 0.2 0.3 0.4 0.5 0.6 0.7
0.2 0.3 0.4 0.5 0.6 0.7 0.8
0.3 0.4 0.5 0.6 0.7 0.8 0.9
5
Sample Output
0.0000
0.2811

  • 题目关键,看懂题目概率
#include 
using namespace std;
int t,n,x,i,j,cnt;
double a[15],b[15],c[15],ac[15],wa[15],ans,p;
//ac[i]表示团队做对第i题的概率,wa[i]表示团队做错第i题的概率
int main()
{
    cin>>t;
    while(t--)
    {
        cin>>n;
        for(i=0; i<n; i++)
            cin>>a[i];
        for(i=0; i<n; i++)
            cin>>b[i];
        for(i=0; i<n; i++)
            cin>>c[i];
        cin>>x;//输入
        ans=0;
        for(i=0; i<(1<<n); i++)//开始二进制枚举
        {
            p=1;
            cnt=0;
            for(j=0; j<n; j++)//模板
            {
                wa[j]=(1-a[j])*(1-b[j])*(1-c[j]);
                //wa【j】3个人都不会做这题,即团队做不出这题的概率;
                ac[j]=1-wa[j];//概率计算
                if(i&(1<<j))  //判断条件                                                                                                      
                {
                    p=p*ac[j];  //cnt记录团队ac数量
                    cnt++;
                }
                else
                    p=p*wa[j];//cnt记录团队wa数量
            }
            if(cnt==x)//如果达到要求的题数
                ans+=p;//加上概率
        }
        printf("%.4lf\n",ans);
    }
    return 0;
}


  • 下节提示
  • acm新手小白必看系列之(6)——gcd与lcm精讲及例题

你可能感兴趣的:(acm新手小白必看系列之(5)——枚举进阶例题精讲)