题目链接
题目解法
这道题有一个很妙的结论:
任何三个数
x
,
y
,
z
(
x
<
y
<
z
)
x,y,z(x<y<z)
x,y,z(x<y<z) 满足三进制表示的每一位只有
0
,
1
0,1
0,1,那么
x
+
z
≠
2
y
x+z\ne 2y
x+z=2y
证明:
考虑
y
y
y 三进制的每一位
1
1
1 乘
2
2
2 都为
2
2
2,且
x
+
z
x+z
x+z 与
2
y
2y
2y 都没有进位
如果相同,一定满足
y
y
y 的
1
1
1 位上
x
,
z
x,z
x,z 都为
1
1
1,且
y
y
y 的
0
0
0 位上
x
,
z
x,z
x,z 都为
0
0
0
那么
x
=
y
=
z
x=y=z
x=y=z,矛盾
考虑先构造一个序列,然后调整
注意到一个性质:不考虑
M
M
M 的前提下,一个合法的序列每个数都加上一个相同的数,仍是一个合法的序列
所以可以把所有数的和逼近到与
M
M
M 差
n
n
n 以内
那么可以选择一些数
+
1
+1
+1,这需要我们一开始构造的序列空出第一位
所以构造的顺序是这样的:
空出最低位,其他位构造出一个合法的序列(不考虑
M
M
M)
然后把一些数
+
1
+1
+1 来让数列和
S
S
S 与
M
M
M 模
n
n
n 同余
然后每个数加上一个相同的数
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N(10100);
int n,m,sum,ans[N],bs[20];
bool a[N];
inline int read(){
int FF=0,RR=1;
char ch=getchar();
for(;!isdigit(ch);ch=getchar()) if(ch=='-') RR=-1;
for(;isdigit(ch);ch=getchar()) FF=(FF<<1)+(FF<<3)+ch-48;
return FF*RR;
}
void adjust(){
int add1=0,add2=0;
if(m<sum) add1=(m-sum)%n+n,add2=(m-sum)/n-1;
else add1=(m-sum)%n,add2=(m-sum)/n;
for(int i=1;i<=add1;i++) ans[i]++;
for(int i=1;i<=n;i++) ans[i]+=add2;
}
signed main(){
n=read(),m=read();
bs[0]=1;
for(int i=1;i<=15;i++) bs[i]=bs[i-1]*3;
for(int i=1;i<=n;i++){
int t=i*2;
for(int j=15;j>=0;j--)
if(t>>j&1) ans[i]+=bs[j];
sum+=ans[i];
}
adjust();
for(int i=1;i<=n;i++) printf("%lld ",ans[i]);
return 0;
}