题解:P11277 世界沉睡童话
人类智慧,一堆地方不会证,欢迎证明或 hack。
首先注意到:
考虑这么一种构造:若干个
则有:
一通整理: :::info[过程]{open}
::: 得出这么个结论:
考虑枚举
这里我用的是贪心解法。考虑先放
接下来把后面的
接下来,忽略第一个数,从第二个数开始合并即可。
合并到最后,如果第二个方程左右相等则已经找到解了,否则无解。
正确性似乎不会严谨证明,但是好像比较显然?
先不管了。最人类智慧的还在后面呢。
这样直接做是过不了的,会 TLE
我们会发现,似乎
竟然过了!时间竟然还和正解不相上下!
做完了。 :::success[code]
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define fi first
#define se second
#define pii pair<int,int>
#define lowbit(x) ((x)&(-(x)))
#define popc(x) __builtin_popcountll(x)
#define ctz(x) __builtin_ctzll(x)
#define clz(x) __builtin_clzll(x)
#define double long double
#define sqrt(x) sqrtl(x)
#define cbrt(x) cbrtl(x)
#define pow(x,y) powl(x,y)
#define vct basic_string
#define ms(x,v) memset(x,v,sizeof(x))
const int N=5e5+10,mod=998244353;
int c,x[N];
bool find(int n,int s)
{
c=0;
if(s<n) return 0;
int t=n,us=0;
while(us!=n)
{
x[++c]=1;
us++;
int sp=2;
while(t+sp<=s&&us!=n) t+=sp,sp+=2,x[c]++,us++;
}
return t==s;
}
signed main()
{
ios::sync_with_stdio(0);
cin.tie(0),cout.tie(0);
int n,k;
cin>>n>>k;
int s=2*k+n;
for(x[0]=n;x[0]>=0;x[0]--) if(find(n-x[0],s-x[0]*(2*n-x[0])))
{
for(int i=1;i<=x[0];i++) cout<<1<<' ';
for(int i=1;i<=c;i++) for(int j=1;j<=x[i];j++) cout<<n+i-1<<' ';
return 0;
}
return 0;
}
:::