这场好有毒啊~进去就被C、E俩结论题关了。
赛后补题发现其实D也很容易构造。
题意是请你构造一个长度在50以内的序列,第一项是a,最后一项是b,序列的每一项都是前缀和再加上$r_{i}$,然后规定$1<=r_{i}<=m$。
显然我们可以发现在$r_{i}$对$x_{j}$的贡献是非常容易计算的
for(i=1;i<=50;i++)for(i0=0;i0<i;i0++)dic[i]+=dic[i0];
用dic[i]表示$r_{p}$对$x_{p+i}$的贡献。
然后我们要规定序列的长度,这个的话,我是求出每个长度的上下界,如果b在上下界内,这个长度就可行,如果b大于上界后同时也大于下界,那显然就要输出-1。
有了长度之后我们就直接求解每一项的具体值即可,在原来的上界的基础上,我们可以减回$[0,m-1]$,来使得$x_{n}$符合我们的要求减小到b。
以下是具体实现代码:
#include<bits/stdc++.h> using namespace std; int i,i0,n; long long L[55],R[55],preL[55],preR[55],dic[55]; int main() { dic[0]=1; for(i=1;i<=50;i++)for(i0=0;i0<i;i0++)dic[i]+=dic[i0]; int T; scanf("%d",&T); while(T--) { long long a,b,m; scanf("%lld %lld %lld",&a,&b,&m); preL[1]=L[1]=preR[1]=R[1]=a; if(a==b) { printf("1 %lld\n",a); continue; } for(i=2;1;i++) { L[i]=preL[i-1]+1; preL[i]=preL[i-1]+L[i]; R[i]=preR[i-1]+m; preR[i]=preR[i-1]+R[i]; if(R[i]>=b)break; } if(L[i]>b)printf("-1\n"); else { n=i; for(i=2;i<=n;i++) { if(R[n]>b) { long long d=min(m-1,(R[n]-b)/dic[n-i]); for(i0=i;i0<=n;i0++)R[i0]-=d*dic[i0-i]; } } printf("%d",n); for(i=1;i<=n;i++)printf(" %lld",R[i]); printf("\n"); } } return 0; }