4621 三个整数:
解题思路:
根据条件得直接输出b, c, c即可满足条件。#include <iostream> using namespace std; int main() { int a, b, c, d; cin >> a >> b >> c >> d; cout << b << ' ' << c << ' ' << c << endl; return 0; }
4622. 整数拆分
题目:
我们规定 f(x)(x≥2)表示整数 x 的除本身之外的最大因数。 例如,f(6)=3,f(25)=5,f(2)=1。 现在,给定一个整数 n,请你将其拆分为 k 份 n1,n2,…,nk(也可以不拆分,即 k=1),要求: n1+n2+…+nk=n 对于 1≤i≤k,ni≥2 始终成立。 f(n1)+f(n2)+…+f(nk) 的值应尽可能小。 输出 f(n1)+f(n2)+…+f(nk) 的最小可能值。 输入格式 一个整数 n。 输出格式 一个整数,表示 f(n1)+f(n2)+…+f(nk) 的最小可能值。 数据范围 前 4 个测试点满足 2≤n≤30。 所有测试点满足 2≤n≤2×109。 输入样例1: 4 输出样例1: 2 输入样例2: 27 输出样例2: 3
解题思路:
可以分类讨论:1:若n为质数,则答案定为1
2:若n为偶数:由哥德巴赫的猜想:任何一个大于2的偶数都可以拆成2个质数之和即:
f(n) == f(质数1) + f(质数2) == 2
3:若n既不是质数也是不是偶数,即n为奇合数:
{
奇合数:奇合数是指不能被2整除的合数,除了偶合数之外的其余合数。
若不拆:则f(n) > 2:
若拆:则它一定由一个偶数x1 + 另一个数x2组成:
首先要想使得f(x1) + f(x2)最小我们只要使得f(x1), f(x2)分别最小即可:
所以x1我们可以选择2, 他的f(2)是最小的:
我们已经减去2了所以只要判断n - 2的类型即可:
{
因为一个数除了1以外他都是质数或合数的其中一类,所以我们可以把n - 2分为
质数或合数
若n - 2 == 质数:则f(x1) + f(x2) == f(2) + f(质数) == 2;
若n - 2 == 合数:
{
若不拆分则f(n - 2) + f(x1) >= 3
若拆分则可拆为两个f(n[i])(i = 1, 2, 3)即f(x1) + f(n1) + f(n2) >= 3;
}
接下来我们只需要证明上述情况能等于3即可
由哥德巴赫的猜想:任一大于5的整数都可写成三个质数之和
所以它可以取3.
}
}
代码如下:
#include <iostream> using namespace std; bool is_prime(int n) { for (int i = 2; i <= n / i; i ++ ) if (n % i == 0) return false; return true; } int main() { int n; cin >> n; if (n == 2) puts("1"); if (is_prime(n)) puts("1"); else if (n % 2 == 0 || is_prime(n - 2)) puts("2"); else puts("3"); return 0; }
AcWing 4623. 买糖果
n 个糖果店,围成一圈。 店铺按顺时针顺序从 1 到 n 编号,n 号店铺与 1 号店铺相邻。 第 i 号店铺的单个糖果售价为 ai 元。 李华拿着 T 元钱去购买糖果,具体购买过程如下: 初始时,他位于 1 号店铺。 如果他现有的钱足够在当前店铺购买一个糖果,他就会立即购买一个糖果,否则他将不会在当前店铺购买糖果。随后,不论他是否在当前店铺购买糖果,他都会按顺时针顺序前往下一个店铺。 他将不断重复过程 2,直到剩余的钱在所有店铺都买不起糖果为止。 请问,最终李华一共购买到多少个糖果。 输入格式 第一行包含两个整数 n,T。 第二行包含 n 个整数 a1,a2,…,an。 输出格式 一个整数,表示一共购买到的糖果数量。 数据范围 前 6 个测试点满足 1≤n≤10。 所有测试点满足 1≤n≤2×105,1≤T≤1018,1≤ai≤109。 输入样例1: 3 38 5 2 5 输出样例1: 10 输入样例2: 5 21 2 4 100 2 6 输出样例2: 6
解题思路:
时间复杂度O(nlogn)
直接计算当前的钱可以走多少圈,然后用走的圈数 * 糖果数即为所买的糖果数。
#include <cstdio> #include <iostream> using namespace std; const int N = 200010; typedef long long LL; int n; int w[N]; LL total, res; int main() { cin >> n >> total; for (int i = 0; i < n; i ++ ) scanf("%d", &w[i]); while (true) { LL cnt = 0, sum = 0;//sum为走当前圈所要的钱数,cnt为糖果数 for (int i = 0; i < n; i ++ ) if (w[i] + sum <= total) { sum += w[i]; cnt ++ ; } if (!cnt) break; res += total / sum * cnt;//求出走total / sum 圈所要的糖果数 total %= sum; //走完total/ sum 圈每圈的价格为sum的剩余的钱数。 //当sum > total / 2时, total % sum == total - sum < total / 2 //当sum < total - 2时,total % sum < total / 2 //所以while循环只会走logn次 } cout << res << endl; }