枚举算法
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;
}