题目如下
这道题看似很简单,其实还是得观察一下,要不然就会…
话不多说回到题目,这个题的坑就在于当A,B,C
三个产值相同的时候,再怎么变还是之前的产值,或者也可以通过另外一种方法理解:
通过一个案例来举例:
可以明显的看到,随便一个样例在经过N
次变化后总会相同
仔细分析,通过这个图得知每次两个产值之间的差值可以近似的看为是之前差值的一半,直到N
次之后差值相同,那么N
怎么求呢?
根据我们题目的信息:
- 对于 30% 的评测用例,1≤T≤100,1≤A,B,C,K≤105
- 对于 100%的评测用例,1≤T≤105,1≤A,B,C,K≤109
K最大会到109,每次除以2
,记差值为d
最大为109 ,那么就有 (d = 2x)->
x= logd <=
log1e9
#include<iostream>
#include<algorithm>
#include<cmath>
#include<climits>
using namespace std;
void solve(){cout << (int)log2(1e9); // 输出 29(直接取整)cout << ceil(log2(1e9)); // 输出 30(向上取整)
}
int main()
{ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);int T=1;while(T--){solve();}return 0;
}
通过一个小小的程序,可以得到如果K向下取整得到29,向上取整得到30,取最大K等于30
,所以题目要求给的 K<=109 完全就是诱导(全都是纸老虎),实际根本用不了这么多,这也是超时这么多案例的主要原因,注意!!!!
由于 / 2 是 整数除法(向下取整),每次计算都会 损失精度。我们在这里行行好,给K
的值提升到50
AC代码:
#include<iostream>
#include<algorithm>
#include<cmath>
#include<climits>
using namespace std;
void solve(){int a,b,c,k;int a1,b1,c1;cin>>a>>b>>c>>k;int i=0;k=min(50,k);while(k--){i++;a1=(b+c)/2;b1=(a+c)/2;c1=(a+b)/2;a=a1,b=b1,c=c1;}cout<<a<<" "<<b<<" "<<c<<'\n';
}
int main()
{ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);int T;cin>>T;while(T--){solve();}return 0;
}
也可以直接三个产值相等的时候跳出循环
#include<iostream>
#include<algorithm>
#include<cmath>
#include<climits>
using namespace std;
void solve(){int a,b,c,k;int a1,b1,c1;cin>>a>>b>>c>>k;int i=0;while(k--){i++;a1=(b+c)/2;b1=(a+c)/2;c1=(a+b)/2;a=a1,b=b1,c=c1;if(a==b&&a==c&&b==c) break;}cout<<a<<" "<<b<<" "<<c<<'\n';
}
int main()
{ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);int T;cin>>T;while(T--){solve();}return 0;
}
实测第二个写法跑的速度快一点,稳妥一点