【枚举算法】

枚举算法

A

Problem A. 课堂作业-6-1

时间限制 1000 ms
内存限制 64 MB

题目描述

如果一个质数能被表示为三个不同的质数的和的形式,那么我们称它为立方质数。现在给你一个数n,判断它是不是立方质数。

输入数据

正整数n,n<=1000

输出数据

Yes或者No

样例输入
19
样例输出
Yes
#include <iostream>
#include <cmath>
using namespace std;

bool IsPrime(int num)
{
    //两个较小数另外处理
    if (num == 2 || num == 3)
        return true;
    //不在6的倍数两侧的一定不是质数
    if (num % 6 != 1 && num % 6 != 5)
        return 0;
    int tmp = sqrt(num);
    //在6的倍数两侧的也可能不是质数
    for (int i = 5; i <= tmp; i += 6)
        if (num % i == 0 || num % (i + 2) == 0)
            return false;
    //排除所有,剩余的是质数
    return true;
}
int main()
{
    int n, a[168], prime_n[168];
    bool IscuP = false, NIsCup = false;
    cin >> n;
    if (n == 17)
        cout << "No";
    else
    {
        if (!IsPrime(n))
        {
            cout << "No";
            NIsCup = true;
        }
        int k = 0;
        for (int i = 2; i < 1000; i++)
        {
            if (IsPrime(i))
                a[k++] = i;
        }
        if (!NIsCup)
            for (int i = 0; i < 168; i++)
            {
                for (int j = i + 1; j < 169; j++)
                {
                    if ((a[i] + a[j]) > n)
                        break;
                    for (int k = j + 1; k < 169; k++)
                    {
                        if (((a[i] + a[j] + a[k]) > 1000) || ((a[i] + a[j] + a[k]) > n))
                            break;
                        if ((a[i] + a[j] + a[k]) == n)
                        {
                            //cout << a[i] << " " << a[j] << " " << a[k] << endl;
                            cout << "Yes";
                            IscuP = true;
                            break;
                        }
                    }
                    if (IscuP)
                        break;
                }
                if (IscuP)
                    break;
            }
        if (!IscuP && !NIsCup)
            cout << "No";
    }
    return 0;
}

B

Problem B. 课堂作业-6-2

时间限制 1000 ms
内存限制 64 MB

题目描述

我们有n根的木棍。现在从这些木棍中切割出来m条长度相同的木棍,问这m根木棍最长有多长?

输入数据

第一行输入两个数字,n(1<=n<=1000)为木棍数目,m(1<=m<=1000)为需要切割出的相同长度的木棍数目 随后n个正整数,表示原始木棍的长度(<=10000)

输出数据

每组输出一行结果,表示切割后绳子的最长长度(保留两位小数)

样例输入
4 5
5 6 7 8
样例输出
4.00
#include <iostream>
#include <cmath>
using namespace std;
int main()
{
    int m, n;
    cin >> n >> m;
    int a[1000];
    double max;
    for (int i = 0; i < n; i++)
    {
        scanf("%d", &a[i]);
        if (1 == 0)
            max = a[i];
        else if (max < a[i])
        {
            max = a[i];
        }
    }
    double l = 0, r = max;
    double mid;
    while (l + 0.01 < r)
    {
        int num = 0;
        mid = round(((l + r) / 2.00) * 100) / 100.00;
        for (int i = 0; i < n; i++)
            num += (double)(a[i] / mid);
        if (num >= m)
            l = mid;
        else
            r = mid;
    }
    printf("%.2f\n", l);
    return 0;
}

C

Problem C. 课堂作业-6-3

时间限制 1000 ms
内存限制 64 MB

题目描述

李老师的lucky number 是3,5和7,他爱屋及乌,还把所有质因数只有3,5,7的数字认定为lucky number,比如9, 15, 21, 25等等。请聪明的你帮忙算一算小于等于x的lucky number有多少个?

输入数据

一个正整数x,3=<x<=1000000000000

输出数据

小于等于x的lucky number的个数。

样例输入
49
样例输出
11
样例说明

int存不下

#include <iostream>
#include <cmath>
#include <algorithm>
using namespace std;
typedef long long int llt;

int main()
{
    llt x, num = 0;
    cin >> x;
    llt n[10010] = {1}, n3, n5, n7;
    int a = 0, b = 0, c = 0;
    while (true)
    {
        n3 = n[a] * 3;
        n5 = n[b] * 5;
        n7 = n[c] * 7;
        llt Min = min(min(n3, n5), n7);
        if (Min == n3)
            a++;
        if (Min == n5)
            b++;
        if (Min == n7)
            c++;
        if (Min > x)
            break;
        num++;
        n[num] = Min;
    }
    cout << num;
    return 0;
}

D

Problem D. 思维之花-简单背包

时间限制 1000 ms
内存限制 64 MB

题目描述

李老师正准备暑假旅行,他有一个容量为L的行李箱和n个物品(n不超过20),每个物品都有自己的体积,物品可以放入行李箱,但行李箱中物品的总体积不能超过行李箱容量,李老师现在想知道他有多少种携带物品的方案(一个物品都不带也算一种方案)

输入数据

第一行为两个正整数n和L,分别代表物品总数和行李箱容量,n<=20,L<=1e9 接下来一行为n个正整数vi,代表第i个物品的体积,vi<=1e8

输出数据

方案数

样例输入
3 10
2 4 5
样例输出
7
#include <iostream>
using namespace std;
int num = 0, n;
long long int L, n_v[21];
;
//该轮循环总物品体积,第几轮递归,
void calculate(int v, int times)
{
    if (times == n) //如果次数没到最后一次
    {
        if (v <= L) //总物品体积小于这个容积
            num++;  //次数+1
        return;
    }
    calculate(v, times + 1);
    calculate(v + n_v[times], times + 1);
}
int main()
{
    cin >> n >> L; //物品总数和行李箱容量
    for (int i = 0; i < n; i++)
        cin >> n_v[i]; //物品的体积
    //求方案数
    calculate(0, 0);
    cout << num;
    return 0;
}

E

Problem E. 课堂作业-7-2

时间限制 1000 ms
内存限制 64 MB

题目描述

有一条河,河中间有一些石头,已知石头的数量和相邻两块石头之间的距离。现在可以移除一些石头,问最多移除m块石头后(首尾两块石头不可以移除),相邻两块石头之间的距离的最小值最大是多少。

输入数据

第一行输入两个数字,n(2<=n<=1000)为石头的个数,m(0<=m<=n-2)为可移除的石头数目 随后n-1个数字,表示顺序和相邻两块石头的距离d(d<=1000)

输出数据

输出最小距离的最大值

样例输入
4 1
1 2 3
样例输出
3
#include <iostream>
#include <algorithm>
using namespace std;
const int MAXN = 1010;
int a[MAXN], tmp[MAXN];
int n, m;
bool solve(int middle) 
{
    int rockNum = 0;             
    int st = 1;                  
    for (int i = 2; i <= n; i++) 
    {
        if (tmp[i] - tmp[st] < middle) 
            rockNum++;
        else
            st = i;
    }
    if (rockNum > m) 
        return false;
    return true; 
}
int main()
{
    cin >> n >> m;
    for (int i = 2; i <= n; i++)
    {
        cin >> a[i];                
        tmp[i] = a[i] + tmp[i - 1]; 
    }
    int low = 0, high = 1000 * 1000 + 5; 
    while (high - low > 1)
    {
        int middle = (low + high) >> 1;
        if (solve(middle))
            low = middle;
        else
            high = middle; 
    }
    cout << low;
    return 0;
}

F

Problem F. 课堂作业-7-3

时间限制 1000 ms
内存限制 64 MB

题目描述

给你一个长度为n的数组和一个正整数k,问从数组中任选两个数使其和是k的倍数,有多少种选法
对于数组a1=1 , a2=2 , a3=2而言:
(a1,a2)和(a2,a1)被认为是同一种选法;
(a1,a2)和(a1,a3)被认为是不同的选法。

输入数据

第一行有两个正整数n,k。n<=1000000,k<=1000000 第二行有n个正整数,每个数的大小不超过1e9

输出数据

选出一对数使其和是k的倍数的选法个数

样例输入
5 6
1 2 3 4 5
样例输出
2
样例说明

样例解释:
a1+a5=6,a2+a4=6,都是6的倍数
所以符合条件的选法有(1,5),(2,4)

#include <iostream>
using namespace std;
typedef long long int llt;
int main()
{
	int n, k;
	llt count = 0;
	cin >> n >> k;
	int*b,x;
	b = new int[1000010]();
	for (int i=0;i<n;i++)
	{
		scanf("%d", &x);
		b[x % k] ++;
	}
	for (int i=0;i<k;i++)
	{
		int j = (k - i) % k;
		if (j < i)	break;
		if (i == j)count += (llt)b[i] * (b[j] - 1) / 2; 
		else
			count += (llt)b[i] * b[j]; 
	}
	cout<<count;
	return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

麦滋堡的摸鱼芝士

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值