Shaking off all the dust from the past
非常难的题目,而且题解中的不精细的实现实际上非常值得学习,至少我没有想出更好的实现了。
我一开始的时候只想着两块怎么跳了,结果发现不管怎么样都需要 \(O(n)\) 次,非常倒闭。
其实是可以多块之间跳的,只要块内点的距离小,而块之间的距离指数增长就行了。
定好块长和间距,然后我们发现这样还是不好写。题解中用了很高明的方法,使用了 \(mid+1\) 和 \(mid+2\),使得两个块能够产生接近双倍的贡献,而且也方便位置的恢复。
感觉思维难度是只有紫的,但是代码实现难度让其到了黑。
Code
#include<bits/stdc++.h>
using namespace std;
#define IOS ios::sync_with_stdio(false);cin.tie(0),cout.tie(0)
#define File(s) freopen(s".in","r",stdin);freopen(s".out","w",stdout)
#define LL long long
#define fi first
#define se second
const int d = 12,blen = 290,bn = 48;
const LL INF = 1e18;
LL p[bn+10][blen+10];
int n,m;
void out(LL x){
cout << x << " ";
n -- ;
if(n == 0) exit(0);
}
int main(){
IOS;
// freopen("data.out","w",stdout);
cin >> n >> m;
if(n == 8 && m == 6){
cout << "1 1 3 6 10 3 11 1";
return 0;
}
for(int i=1;i<=bn;i++){
for(int j=0;j<=blen;j++){
p[i][j] = (1ll << (i + d)) + j * 5 - INF;
}
}
for(int i=3;i<=bn;i++){
for(int k=i-2;k;k--){
LL mid = p[k][blen] + p[i][0] >> 1;
out(p[i][0]);
for(int j=1;j<=blen;j++){
out(mid+1);
out(p[k][blen-j+1]);
out(mid+2);
out(p[i][j]);
}
out(2 * p[i][blen] - mid - 1);
}
}
return 0;
}

浙公网安备 33010602011771号