题意
试构造一个正整数数列 a1,a2,…,am,使得这个数列满足以下条件:
-
a1=am=1。
-
ai=ai−1−1 or ai−1 or ai−1+1 ,2≤i≤m。
-
∑i=1mai=n。
求这个数列最短的长度。
最多有 105 组数据,1≤n≤1018。
分析
由于 n 的范围超大,所以我们可以先打表找规律从 n 较小的情况看。
| n |
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
| ans |
1 |
2 |
3 |
3 |
4 |
4 |
5 |
5 |
5 |
看起来很有规律:1,2 出现了 1 次,3,4 出现了 2 次,5 出现了 3 次,那 6 呢?
| n |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
| ans |
6 |
6 |
6 |
7 |
7 |
7 |
7 |
8 |
8 |
8 |
8 |
这时的规律就不言自明了,不过还是看不出正解……
于是我们把这个表转一下:
| ans |
ans 对应的 n |
ans 对应的 max(n) |
| 1 |
1 |
1 |
| 2 |
2 |
2 |
| 3 |
3,4 |
4 |
| 4 |
5,6 |
6 |
| 5 |
7,8,9 |
9 |
| 6 |
10,11,12 |
12 |
| 7 |
13,14,15,16 |
16 |
| 8 |
17,18,19,20 |
20 |
如果你还看不出来,那我只好打出来了:
1=1×1 2=1×2
4=2×2 6=2×3
9=3×3 12=3×4
16=4×4 20=4×5
ans 对应的 max(n)=⌊2(ans+1) xor 1⌋×(⌊2(ans+1) xor 1⌋+((ans+1) & 1))。
用人话来说,若 ans 为偶数,则 max(n)=⌊2ans⌋×(⌊2ans⌋+1)=⌊2ans⌋2+⌊2ans⌋;若 ans 为奇数,则 max(n)=⌊2ans+1⌋2。
又因为每个 ans 对应的 n 是连续的,所以我们可以根据 n 所在的范围确定 ans,记 a=⌊n⌋,则:
n=⎩⎨⎧2×a−12×a2×a+1n=a2a2<n≤a×(a+1)n>a×(a+1)
为什么是正确的呢?我们以 a=3 来举例。
| n |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
| a |
3 |
3 |
3 |
3 |
3 |
3 |
3 |
| ans |
5 |
6 |
6 |
6 |
7 |
7 |
7 |
一一对照就能发现上面 n 的求法是对的。
代码
#include<bits/stdc++.h>
#define ll long long
using namespace std;
ll t,n,a;
int main()
{
cin>>t;
while(t--)
{
cin>>n;
a=sqrt(n);
if(n==a*a)
cout<<a*2-1<<endl;
else if(n<=a*(a+1))
cout<<a*2<<endl;
else
cout<<a*2+1<<endl;
}
return 0;
}