枚举算法(暑期基础班)

目录

A. 百钱百鸡

说明

输入格式

输出格式

B. 换零钱 [1*] 

说明

C. 100以内的素数 

D. 【数组】七位完全平方数(sevensqr) 

说明

输入格式

输出格式

E. 牌型种数 

F. 陶陶摘苹果 

题目描述

输入格式

输出格式

G. 数字游戏 (Number Games) 

题目描述

输入格式

输出格式

输入数据 1

输出数据 1

数据范围与提示

H. 分糖果 

题目背景

题目描述

输入格式

输出格式

输入数据 1

输出数据 1

样例 1 说明

输入数据 2

输出数据 2

样例 2 说明

样例 3

数据范围与提示

I. 优秀的拆分 (Excellent Split) 

题目描述

输入格式

输出格式

输入数据 1

输出数据 1

输入数据 2

输出数据 2

数据范围与提示

J. 完全平方数问题 


A. 百钱百鸡

说明

用100元钱买100只鸡。公鸡5元1只,母鸡3元1只,小鸡1元3只。请问公鸡,母鸡,小鸡各应该买多少只?

输入格式

输出格式

每种买法占一行,由3个数组成,顺序为 公鸡数 母鸡数 小鸡数。每个数字空格隔开。

 

公鸡最多20只,母鸡最多33只,小鸡最多99只,然后满足百钱、百鸡即可 

#include<bits/stdc++.h>
using namespace std;
#define ll long long

int main(){
    for(int i=0;i<=20;i++){
        for(int j=0;j<=34;j++){
            for(int k=0;k<=100;k+=3){
                if(i*5+j*3+k/3==100&&i+j+k==100){
                    cout<<i<<' '<<j<<' '<<k<<'\n';
                }
            }
        }
    }
    return 0;
}

B. 换零钱 [1*] 

说明

某人想将手中的一张面值 100 元的人民币换成 5 元、 1 元和 0.5 元面值的票子,但要求换正好 100 张,且每种票子至少一张。问:有几种换法?
 
提示: 用三重循环。想一想如何减少循环的次数。
5 元、 1 元和 0.5 元最多各需要几张。记得要求正好换 100 张,总价值100元。
循环变量代表某个币种的张数。

 

和上一题差不多,只是本题只需要输出方案数即可 

#include<bits/stdc++.h>
using namespace std;
#define ll long long

int main(){
    int cnt=0;
    for(int i=1;i<=20;i++){
        for(int j=1;j<=100;j++){
            for(int k=2;k<=100;k+=2){
                if(i*5+j+k/2==100&&i+j+k==100){
                    cnt++;
                }
            }
        }
    }
    cout<<cnt;
    return 0;
}

C. 100以内的素数 

 编程求100以内的素数,并5个一行输出,每行数与数之间用一个空格隔开。

 纯基础题了

#include<bits/stdc++.h>
using namespace std;
#define ll long long

int main(){
    int cnt=0;
    for(int i=2;i<=100;i++){
        int a=1;
        for(int j=2;j<=i/j;j++){
            if(i%j==0){
                a=0;
                break;
            }
        }
        if(a){
            cnt++;
            cout<<i<<' ';
            if(cnt==5){
                cnt=0;
                cout<<"\n";
            }
        }
    }
    return 0;
}

D. 【数组】七位完全平方数(sevensqr) 

说明

1267*1267=1605289,表明等式右边是一个七位的完全平方数,而这七个数字互不相同。编程求出所有这样的七位数。

输入格式

无输入。

输出格式

所有符合题意的七位完全平方数,从小到大输出,十个数一行。

 

枚举所有的七位平方数,依次判断是否满足条件即可,然后注意一下输出格式

#include<bits/stdc++.h>
using namespace std;
#define ll long long

int main(){
    int cnt=0;
    for(int i=1000;i*i<10000000;i++){
        int p=i*i;
        int c=1;
        int a[10]={0};
        while(p){
            a[p%10]++;
            if(a[p%10]>1){
                c=0;
                break;
            }
            p/=10;
        }
        if(c){
            cnt++;
            cout<<i*i<<' ';
            if(cnt==10){
                cnt=0;
                cout<<"\n";
            }
        }
    }
    return 0;
}

E. 牌型种数 

小明被劫持到X赌城,被迫与其他3人玩牌。

•一副扑克牌(去掉大小王牌,共52张),均匀发给4个人,每个人13张。

•这时,小明脑子里突然冒出一个问题:

•如果不考虑花色,只考虑点数,也不考虑自己得到的牌的先后顺序,自己手里能拿到的初始牌型组合一共有多少种呢?

从52张中选出13张,排列组合

#include<bits/stdc++.h>
using namespace std;
#define ll long long
int cnt;
int b[15];
void dfs(int x,int w) {//x表示牌数,w表示牌型
    if (x > 13||w>13)return;//牌数超出或者牌型超出直接return
    if (x == 13) {//正好则答案加1
        cnt++;
        return;
    }
    for(int i=4;i>=0;i--)dfs(x+i,w+1);//对于每一种牌型有4,3,2,1,0五种选法
}
int main() {
    dfs(0,0);
    cout << cnt;
    return 0;
}

F. 陶陶摘苹果 

题目描述

陶陶家的院子里有一棵苹果树,每到秋天树上就会结出 1010 个苹果。苹果成熟的时候,陶陶就会跑去摘苹果。陶陶有个 3030 厘米高的板凳,当她不能直接用手摘到苹果的时候,就会踩到板凳上再试试。

现在已知 1010 个苹果到地面的高度,以及陶陶把手伸直的时候能够达到的最大高度,请帮陶陶算一下她能够摘到的苹果的数目。假设他碰到苹果,苹果就会掉下来。

输入格式

第一行包含 1010 个 100到 200 之间(包括 100和 200)的整数(以厘米为单位)分别表示 10 个苹果到地面的高度,两个相邻的整数之间用一个空格隔开。第二行只包括一个 100 到 120 之间(包含 100 和 120 )的整数(以厘米为单位),表示陶陶把手伸直的时候能够达到的最大高度。

输出格式

输出包括一行,这一行只包含一个整数,表示陶陶能够摘到的苹果的数目。

 

只需判断有多少苹果的高度小于等于陶陶手长度+板凳高度即可

#include<bits/stdc++.h>
using namespace std;
#define ll long long
int a[15];
int cnt;
int main(){
    for(int i=0;i<10;i++){
        cin>>a[i];
    }
    int p;
    cin>>p;
    for(int i=0;i<10;i++){
        if(a[i]<=p+30)cnt++;
    }
    cout<<cnt;
    return 0;
}

G. 数字游戏 (Number Games) 

题目描述

小 K 同学向小 P 同学发送了一个长度为 88 的 0101 字符串来玩数字游戏,小 P 同学想要知道字符串中究竟有多少个 11。

注意:0101 字符串为每一个字符是 00 或者 11 的字符串,如 101(不含双引号)为一个长度为 33 的 0101 字符串。

输入格式

输入文件只有一行,一个长度为 88 的 0101 字符串 �s。

输出格式

输出文件只有一行,包含一个整数,即 0101 字符串中字符 11 的个数。

输入数据 1

00010100 

Copy

输出数据 1

2

Copy

数据范围与提示

对于 20%20% 的数据,保证输入的字符全部为 00。

对于 100%100% 的数据,输入只可能包含字符 00 和字符 11,字符串长度固定为 88。

 

简单枚举,统计字符串中1的个数

#include<bits/stdc++.h>
using namespace std;
#define ll long long

int main(){
    string s;
    cin>>s;
    int cnt=0;
    for(int i=0;i<8;i++){
        if(s[i]=='1')cnt++;
    }
    cout<<cnt;
    return 0;
}

H. 分糖果 

题目背景

红太阳幼儿园的小朋友们开始分糖果啦!

题目描述

红太阳幼儿园有 n 个小朋友,你是其中之一。保证 �≥2n≥2。

有一天你在幼儿园的后花园里发现无穷多颗糖果,你打算拿一些糖果回去分给幼儿 园的小朋友们。

由于你只是个平平无奇的幼儿园小朋友,所以你的体力有限,至多只能拿 R 块糖回去。

但是拿的太少不够分的,所以你至少要拿 �L 块糖回去。保证 �≤�≤�n≤L≤R。也就是说,如果你拿了 �k 块糖,那么你需要保证 �≤�≤�L≤k≤R。

如果你拿了 �k 块糖,你将把这 �k 块糖放到篮子里,并要求大家按照如下方案分糖果:只要篮子里有不少于 �n 块糖果,幼儿园的所有 �n 个小朋友(包括你自己)都从篮子中拿走恰好一块糖,直到篮子里的糖数量少于 �n 块。此时篮子里剩余的糖果均归你所有——这些糖果是作为你搬糖果的奖励

作为幼儿园高质量小朋友,你希望让作为你搬糖果的奖励的糖果数量(而不是你最后获得的总糖果数量!)尽可能多;因此你需要写一个程序,依次输入 �,�,�n,L,R,并输出你最多能获得多少作为你搬糖果的奖励的糖果数量。

输入格式

从文件 candy.in 中读入数据。

输入一行,包含三个正整数 �,�,�n,L,R,分别表示小朋友的个数、糖果数量的下界和界。

输出格式

输出到文件 candy.out 中。

输出一行一个整数,表示你最多能获得的作为你搬糖果的奖励的糖果数量。

输入数据 1

7 16 23

Copy

输出数据 1

6

Copy

样例 1 说明

拿 �=20k=20 块糖放入篮子里。

篮子里现在糖果数 20≥�=720≥n=7,因此所有小朋友获得一块糖;

篮子里现在糖果数变成 13≥�=713≥n=7,因此所有小朋友获得一块糖;

篮子里现在糖果数变成 6<�=76<n=7,因此这 66 块糖是作为你搬糖果的奖励

容易发现,你获得的作为你搬糖果的奖励的糖果数量不可能超过 66 块(不然,篮子里的糖果数量最后仍然不少于 �n,需要继续每个小朋友拿一块),因此答案是 66。

输入数据 2

10 14 18

Copy

输出数据 2

8

Copy

样例 2 说明

容易发现,当你拿的糖数量 �k 满足 14=�≤�≤�=1814=L≤k≤R=18 时,所有小朋友获得一块糖后,剩下的 �−10k−10 块糖总是 作为你搬糖果的奖励 的糖果数量,因此拿 �=18k=18 块是最优解,答案是 88。

样例 3

见选手目录下的 candy3.in 与 candy3.ans

数据范围与提示

测试点�≤n≤�≤R≤�−�≤R−L≤
112255
22551010
33103103
44105105
5510310310910900
66103103
77105105105105
88109109109109
99
1010

对于所有数据,保证 2≤�≤�≤�≤1092≤n≤L≤R≤109。

 

如果左边界和右边界除以n的的结果大于等于1,那么直接输出n-1即可

如果不够,就输出右边界对n取余的结果 

#include<bits/stdc++.h>
using namespace std;
#define ll long long

int main(){
    int n,l,r;
    cin>>n>>l>>r;
    int p=l/n;
    //int pp=l%n;
    int q=r/n;
    int qq=r%n;
    if(q-p>=1){
        cout<<n-1;
    }
    else{
        cout<<qq;
    }
    return 0;
}

I. 优秀的拆分 (Excellent Split) 

题目描述

一般来说,一个正整数可以拆分成若干个正整数的和。

例如,1=11=1,10=1+2+3+410=1+2+3+4 等。对于正整数 �n 的一种特定拆分,我们称它为“优秀的”,当且仅当在这种拆分下,�n 被分解为了若干个不同的 22 的正整数次幂。注意,一个数 �x 能被表示成 22 的正整数次幂,当且仅当 �x 能通过正整数个 22 相乘在一起得到。

例如,10=8+2=23+2110=8+2=23+21 是一个优秀的拆分。但是,7=4+2+1=22+21+207=4+2+1=22+21+20 就不是一个优秀的拆分,因为 11 不是 22 的正整数次幂。

现在,给定正整数 �n,你需要判断这个数的所有拆分中,是否存在优秀的拆分。若存在,请你给出具体的拆分方案。

输入格式

输入只有一行,一个整数 �n,代表需要判断的数。

输出格式

如果这个数的所有拆分中,存在优秀的拆分。那么,你需要从大到小输出这个拆分中的每一个数,相邻两个数之间用一个空格隔开。可以证明,在规定了拆分数字的顺序后,该拆分方案是唯一的。

若不存在优秀的拆分,输出 -1

输入数据 1

6 

Copy

输出数据 1

4 2

Copy

输入数据 2

7 

Copy

输出数据 2

-1

Copy

数据范围与提示

对于 20%20% 的数据,�≤10n≤10。

对于另外 20%20% 的数据,保证 �n 为奇数。

对于另外 20%20% 的数据,保证 �n 为 22 的正整数次幂。

对于 80%80% 的数据,�≤1024n≤1024。

对于 100%100% 的数据,1≤�≤1071≤n≤107。

 

首先打表求出10^7内所有2的正整数次幂的结果,如果是奇数直接输出-1,如果是偶数每次减去能减的最大值,直到n<2为止;若n正好为0则输出结果,否则输出-1 

#include<bits/stdc++.h>
using namespace std;
#define ll long long
int a[100];
int cnt=0;
int main(){
    for(int i=2;i<=10000000;i*=2)a[cnt++]=i;
    int n;
    cin>>n;
    if(n%2!=0)cout<<-1;
    else{
        vector<int>v;
        while(n>=a[0]){
            int p=upper_bound(a,a+cnt,n)-a;
            v.push_back(a[p-1]);
            n-=a[p-1];
        }
        if(n)cout<<-1;
        else for(int i=0;i<v.size();i++)cout<<v[i]<<' ';
    }
    return 0;
}

J. 完全平方数问题 

用0至9这10个数字组成一位数、两位数、三位数、四位数各一个,使它们都是非零的完全平方数.例如1,36,784,9025就是满足条件的一种分法.输出有多少种方案。 

dfs爆搜求结果 

#include<bits/stdc++.h>
using namespace std;
#define ll long long
vector<int>v1,v2,v3,v4;
int a[10]={0};
int cnt;
void dfs(int x){//x表示选到第几位了
    if(x==5){
        int q=0;
        for(int i=0;i<10;i++){
            if(a[i]==1)q++;
        }
        if(q==10)//如果每个数出现1次就答案+1
            cnt++;
        return;
    }
    if(x==2){
        for(int i=0;i<v2.size();i++){
            int t=v2[i];
            while(t){
                a[t%10]++;
                t/=10;
            }
            //先标记
            dfs(x+1);
            //再还原现场
            t=v2[i];
            while(t){
                a[t%10]--;
                t/=10;
            }
        }
    }
    if(x==3){
        for(int i=0;i<v3.size();i++){
            int t=v3[i];
            while(t){
                a[t%10]++;
                t/=10;
            }
            dfs(x+1);
            t=v3[i];
            while(t){
                a[t%10]--;
                t/=10;
            }
        }
    }
    if(x==4){
        for(int i=0;i<v4.size();i++){
            int t=v4[i];
            while(t){
                a[t%10]++;
                t/=10;
            }
            dfs(x+1);
            t=v4[i];
            while(t){
                a[t%10]--;
                t/=10;
            }
        }
    }
}
int main(){
    for(int i=1;i<100;i++){
        if(i*i<10)v1.push_back(i*i);//1位数
        else if(i*i<100)v2.push_back(i*i);//2位数
        else if(i*i<1000)v3.push_back(i*i);//3位数
        else if(i*i<10000)v4.push_back(i*i);//4位数
    }
    for(int i=0;i<v1.size();i++){
        a[v1[i]]=1;
        dfs(2);
        a[v1[i]]=0;
    }
    cout<<cnt;//输出结果
    return 0;
}

 

 

 

 

 

 

 

 

 

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值