1104 天长地久 - PAT (Basic Level) Practice (中文) (pintia.cn)
这道题因为数的范围太大(最大1e10)要做剪枝,这是刚开始写的代码:
#include <bits/stdc++.h>
using namespace std;
struct node {
int n, A;
friend bool operator < (node &a, node &b) {
if (a.n != b.n) return a.n < b.n;
return a.A < b.A;
}
}T;
vector<node> V;
int N, k, m, sum1, sum2, temp, I, II;
int gcd(int a, int b) {
if (b == 0) return a;
return gcd(b, a % b);
}
bool is_prime(int x) {
if (x <= 2) return 0;
for (int i = 2; i <= sqrt(x); i++) {
if (x % i == 0) return 0;
}
return 1;
}
int main() {
cin >> N;
for (int i = 1; i <= N; i++) {
V.clear();// 每一轮都要清空
cout << "Case " << i << '\n';
cin >> k >> m;
// if (k * 9 < m) cout << "No Solution\n";
// else {
temp = pow(10, k);
for (int i = temp / 10; i < temp; i++) {
sum1 = 0, sum2 = 0, I = i, II = i + 1;
while (I) {
sum1 += I % 10;
I /= 10;
if (sum1 > m) break;
}
while (II) {
sum2 += II % 10;
II /= 10;
}
if (sum1 == m && is_prime(gcd(m,sum2))) {
T.n = sum2, T.A = i;
V.push_back(T);
}
}
sort(V.begin(), V.end());
if (V.empty()) cout << "No Solution\n";
for (auto &it : V) {
cout << it.n << ' ' << it.A << "\n";
}
}
// }
return 0;
}
优化
把整体范围剪小,假设本来k是6,也就是要枚举1e6的数,现在我们可以枚举1e4的数,在每个数的末尾加上"99"就可以了(观察样例可以发现每个数的后两位都是"99"”,这样就可以把整体范围缩小了
code
#include <bits/stdc++.h>
using namespace std;
struct node {
int n, A;
friend bool operator < (node& a, node& b) {
if (a.n != b.n) return a.n < b.n;
return a.A < b.A;
}
}T;
vector<node> V;
int N, k, m, sum1, sum2, temp, I, II;
int gcd(int a, int b) {
if (b == 0) return a;
return gcd(b, a % b);
}
bool is_prime(int x) {
if (x <= 2) return 0;
for (int i = 2; i <= sqrt(x); i++) {
if (x % i == 0) return 0;
}
return 1;
}
int main() {
cin >> N;
for (int i = 1; i <= N; i++) {
V.clear();// 每一轮都要清空
cout << "Case " << i << '\n';
cin >> k >> m;
if (k * 9 < m) cout << "No Solution\n";
else {
temp = pow(10, k - 2);
for (int i = temp / 10; i < temp; i++) {
sum1 = 18, sum2 = 0, I = i, II = i + 1;
while (I) {
sum1 += I % 10;
I /= 10;
if (sum1 > m) break;
}
while (II) {
sum2 += II % 10;
II /= 10;
}
if (sum1 == m && is_prime(gcd(m, sum2))) {
T.n = sum2, T.A = i;
V.push_back(T);
}
}
sort(V.begin(), V.end());
if (V.empty()) cout << "No Solution\n";
for (auto& it : V) {
cout << it.n << ' ' << it.A << "99\n";
}
}
}
return 0;
}
#include<bits/stdc++.h>
using namespace std;
int N,k,m;
struct node
{
int n;
int a;
}T;
vector<node>v;
bool isprime(int x)
{
if(x<=2)return false;
for(int i=2;i*i<=x;i++)
{
if(x%i==0)return false;
}
return true;
}
int gcd(int a,int b)
{
return b==0?a:gcd(b,a%b);
}
bool cmp(struct node A,struct node B)
{
if(A.n==B.n)return A.a<B.a;
return A.n<B.n;
}
int main()
{
cin>>N;
for(int Case=1;Case<=N;Case++)
{
v.clear();
cout<<"Case "<<Case<<endl;
cin>>k>>m;
//枚举找一下sum1
int digits=pow(10,k-2);
for(int i=digits/10;i<digits;i++)
{
int sum1=18,sum2=0,I=i,II=i+1; //sum1设为18的原因是i的后两位"99"的和为18
while(I)
{
sum1+=I%10;
I/=10;
if(sum1>m)break;
}
while(II)
{
sum2+=II%10;
II/=10;
}
if(sum1==m&&isprime(gcd(sum2,m)))
{
T.n=sum2,T.a=i;
v.push_back(T);
}
}
sort(v.begin(),v.end(),cmp);
if(v.size()==0)cout<<"No Solution\n";
else
{
for(auto &it:v)
{
cout<<it.n<<" "<<it.a<<"99\n";
}
}
}
return 0;
}