P8588
题目描述
先是输入 \(x\) 和 \(k\) 两个整数,\(x\) 是非负整数。
\(k\) 则是要进行 \(k\) 轮操作,对于一轮操作,有以下两个步骤:
\(1.\) 将 \(x\) 增加 \(1\);
\(2.\) 如果 \(x\) 是 \(3\) 的倍数,则将 \(x\) 除以 \(3\)。
题目分析
刚读完题目描述时,我们肯定已经写了一个初步代码:
#include<iostream>
#include<cstdio>
using namespace std;
long long x,k;
int main() {
cin>>x>>k;
while(k--){
x++;
if(x%3==0){
x/=3;
}
}
cout<<x;
return 0;
}
可是这个代码交上去后会TLE六个点,那原因在哪里呢?
我们通过仔细读题和分析,发现如果 \(x\) 为 \(1\) 时,变化规律总是这样的:
1->2->(3->1)->2->(3->1)//用括号括起来的为一次操作
如果设 \(x=1\),\(k=5\),而此时我们再列举一下 \(x\) 与 \(k\) 的值:
x 1 2 1 2 1
k 4 3 2 1 0
我们发现 \(x\) 与 \(k\) 的值是有规律可循的,当 \(x=1\) 时,\(k\) 的值为偶数,当 \(x=2\) 时,\(k\) 的值为奇数。
而加上这个奇偶判断则大大简化了我们的时间复杂度。
这一部分的代码如下:
if(x==1) {
if(k%2==0) {
cout<<1<<endl;
return 0;
}
if(k%2==1) {
cout<<2<<endl;
return 0;
}
}
AC 代码
#include<iostream>
#include<cstdio>
using namespace std;
long long x,k;
int main() {
cin>>x>>k;
while(k--) {
x++;
if(x%3==0) {
x/=3;
}
if(x==1) {
if(k%2==0) {
cout<<1<<endl;
return 0;
}
if(k%2==1) {
cout<<2<<endl;
return 0;
}
}
}
cout<<x;
return 0;
}

浙公网安备 33010602011771号