当前位置:网站首页>PAT乙级“1104 天长地久”DFS优化思路
PAT乙级“1104 天长地久”DFS优化思路
2022-07-03 03:07:00 【Sumzeek丶】
本文介绍了笔者对于B1104的优化思路,AC代码在文末Case3
如果您没有做出答案,笔者强烈建议你按需阅读Case1-3,在看完之后自己动手写一遍代码,自己思考优化思路,并动手实现,本文只起到一个抛砖引玉的作用,欢迎各位大神在评论区分享自己的优化思路。
“天长地久数”是指一个
位正整数
,其满足条件为:
的各位数字之和为
,
的各位数字之和为
,且
与
的最大公约数是一个大于 2 的素数。本题就请你找出这些天长地久数。
输入格式:
输入在第一行给出正整数
,随后 N 行,每行给出一对
和
,其含义如题面所述。
输出格式:
对每一对输入的
和
,首先在一行中输出 Case X,其中 X 是输出的编号(从 1 开始);然后一行输出对应的
和
,数字间以空格分隔。如果解不唯一,则每组解占一行,按
的递增序输出;若仍不唯一,则按
的递增序输出。若解不存在,则在一行中输出 No Solution。
输入样例:
2
6 45
7 80
输出样例:
Case 1
10 189999
10 279999
10 369999
10 459999
10 549999
10 639999
10 729999
10 819999
10 909999
Case 2
No Solution
Case 1:
看到这题笔者首先想到的是使用dfs回溯剪枝进行暴力求解,一共需要自定义三个函数
- isPrime():求素数
- gcd():求最大公因数
- dfs():回溯剪枝
然后通过dfs累加字符串s1,例如k=4,就尝试0000-9999之间的所有情况,最后判断边界条件
- 最大公因数是素数且大于2
- s1的各位相加等于m
若满足边界条件,则打印相应数据。
#include<bits/stdc++.h>
using namespace std;
int N, k, m, n;
string s1;
bool flag;
bool isPrime(int a) {
if (a == 0 || a == 1)return false;
for (int i = 2; i <= sqrt(a); i++) {
if (a % i == 0)return false;
}
return true;
}
int gcd(int a, int b) {
return b == 0 ? a : gcd(b, a % b);
}
int add(string s) {
int sum = 0;
for (int i = 0; i < s.length(); i++)
sum += s[i] - '0';
return sum;
}
void dfs(int step) {
if (step == k) {
int t = gcd(m, add(to_string(stoi(s1) + 1)));
if (t > 2 && add(s1) == m && isPrime(t)) {
printf("%d %s\n", add(to_string(stoi(s1) + 1)), s1.c_str());
flag = true;
}
return;
}
for (int i = 0; i <= 9; i++) {
s1 += i + '0';
dfs(step + 1);
s1.erase(s1.length() - 1);
}
}
int main() {
cin >> N;
int i;
for (i = 0; i < N; i++) {
cin >> k >> m;
s1 = "";
flag = false;
printf("Case %d\n", i + 1);
dfs(0);
if (!flag) cout << "No Solution\n";
}
return 0;
}以下是运行结果,有两个测试点超时,但基本逻辑没问题,故需要优化算法。

Case 2:
我首先想到的是使用一个tepm记录s1字符串还可以使用的最大长度,例如输入(6,44),s1长度为6的时候各位相加必须等于44,假如当s1=99999时,s1的长度只有5但是s1各位累加已经为45,故没有往后尝试的必要(剪枝),可以减少算法运行的时间,同时在dfs中判断边界条件时,有一些语句是冗余的,运算了两次,故也可以用一个临时变量存储,避免多次运算。
#include<bits/stdc++.h>
using namespace std;
int N, k, m, n;
int tmpm;
string s1;
bool flag;
bool isPrime(int a) {
if (a == 0 || a == 1)return false;
for (int i = 2; i <= sqrt(a); i++) {
if (a % i == 0)return false;
}
return true;
}
int gcd(int a, int b) {
return b == 0 ? a : gcd(b, a % b);
}
int add(string s) {
int sum = 0;
for (int i = 0; i < s.length(); i++)
sum += s[i] - '0';
return sum;
}
void dfs(int step) {
if (step == k) {
int n1 = add(to_string(stoi(s1) + 1));
int t = gcd(m, n1);
if (t > 2 && 0 == tmpm && isPrime(t)) {
printf("%d %s\n", n1, s1.c_str());
flag = true;
}
return;
}
for (int i = 0; i <= 9; i++) {
s1 += i + '0';
tmpm -= i;
if (tmpm >= 0)
dfs(step + 1);
tmpm += i;
s1.erase(s1.length() - 1);
}
}
int main() {
cin >> N;
int i;
for (i = 0; i < N; i++) {
printf("Case %d\n", i + 1);
cin >> k >> m;
tmpm = m;
if (k * 9 < m)
cout << "No Solution\n";
else {
s1 = "";
flag = false;
dfs(0);
if (!flag) cout << "No Solution\n";
}
}
return 0;
}
虽然测试点0的耗时降低了,但是测试点2,3还是超时,故还需要优化思路。

Case 3:
本次优化思路来源于老帅比阿的博客,在审题时我们忽略了一个十分重要的点,那就是m和n的最大公因数必须大于2,容易得知s1最后结果的个位一定需要是9,如若不是9则n=m+1,那么n与m的最大公因数一定只能是1,因为相邻两个正整数的最大公因数是1,只有s1的末位是9或末尾是连续的9,加一之后末尾变为0才有可能使m与n的最大公因数大于2。
我们还忽略的题目的一个条件,那就是结果按照n的大小升序排列,故使用矢量组存储结果,再对矢量组进行排序输出,即可得出结果。
#include<bits/stdc++.h>
using namespace std;
int N, k, m, n;
int tmpm;
string s1;
struct node {
int n;
string s;
}tmp;
vector<node> v;
bool cmp(node a, node b) {
if (a.n != b.n) return a.n < b.n;
else return a.s < b.s;
}
bool isPrime(int a) {
if (a == 0 || a == 1)return false;
for (int i = 2; i <= sqrt(a); i++) {
if (a % i == 0)return false;
}
return true;
}
int gcd(int a, int b) {
return b == 0 ? a : gcd(b, a % b);
}
int add(string s) {
int sum = 0;
for (int i = 0; i < s.length(); i++)
sum += s[i] - '0';
return sum;
}
void dfs(int step) {
if (tmpm < 0)
return;
if (step == k - 2) {
s1 += "99";
int n1 = add(to_string(stoi(s1) + 1));
int t = gcd(m, n1);
if (t > 2 && 0 == tmpm && isPrime(t)) {
tmp.n = n1; tmp.s = s1;
v.push_back(tmp);
}
s1.erase(s1.length() - 2);
return;
}
for (int i = 0; i <= 9; i++) {
s1 += i + '0';
tmpm -= i;
dfs(step + 1);
tmpm += i;
s1.erase(s1.length() - 1);
}
}
int main() {
cin >> N;
int i, j;
for (i = 0; i < N; i++) {
printf("Case %d\n", i + 1);
cin >> k >> m;
tmpm = m - 18;
if (k * 9 < m)
cout << "No Solution\n";
else {
s1 = "";
v.clear();
dfs(0);
if (v.size() == 0) cout << "No Solution\n";
else {
sort(v.begin(), v.end(), cmp);
for (j = 0; j < v.size(); j++)
printf("%d %s\n", v[j].n, v[j].s.c_str());
}
}
}
return 0;
}
优化之后的算法可以跑过测试点2,3 ,达成AC。

边栏推荐
- 用docker 连接mysql的过程
- ASP. Net core 6 framework unveiling example demonstration [02]: application development based on routing, MVC and grpc
- [Chongqing Guangdong education] cultural and natural heritage reference materials of China University of Geosciences (Wuhan)
- labelme标记的文件转换为yolov5格式
- SqlServer行转列PIVOT
- Reset or clear NET MemoryStream - Reset or Clear . NET MemoryStream
- I2C subsystem (III): I2C driver
- I2C 子系统(二):I3C spec
- Force freeing memory in PHP
- MySql实战45讲【行锁】
猜你喜欢

Docker install redis

VS code配置虚拟环境

Force deduction ----- the minimum path cost in the grid

TCP 三次握手和四次挥手机制,TCP为什么要三次握手和四次挥手,TCP 连接建立失败处理机制

Thunderbolt Chrome extension caused the data returned by the server JS parsing page data exception

From C to capable -- use the pointer as a function parameter to find out whether the string is a palindrome character

Sqlserver row to column pivot

MySql实战45讲【行锁】

超好用的日志库 logzero

I2C 子系统(一):I2C spec
随机推荐
About HTTP cache control
The core idea of performance optimization, dry goods sharing
MySQL Real combat 45 [SQL query and Update Execution Process]
Kubernetes family container housekeeper pod online Q & A?
Find the storage address of the elements in the two-dimensional array
JMeter performance test JDBC request (query database to obtain database data) use "suggestions collection"
MySql实战45讲【事务隔离】
I2C subsystem (IV): I2C debug
Do you really understand relays?
[C语言]给账号密码进行MD5加密
Three. JS local environment setup
MySQL practice 45 [global lock and table lock]
基于Qt的yolov5工程
Deep learning: multi-layer perceptron and XOR problem (pytoch Implementation)
[principles of multithreading and high concurrency: 1_cpu multi-level cache model]
从C到Capable-----利用指针作为函数参数求字符串是否为回文字符
敏捷认证(Professional Scrum Master)模拟练习题
C # general interface call
How to limit the size of the dictionary- How to limit the size of a dictionary?
Nasvit: neural architecture search of efficient visual converter with gradient conflict perception hypernetwork training