Description
Data Constraint
Solution
根据性质我们可以发现,对于一个f(x),f(x-1),若x为奇数,那么f(x)=f(x/2+1)+f(x/2),f(x-1)=f(x/2),若x为偶数,那么f(x)=f(x/2),f(x-1)=f(x/2)+f(x/2-1)。而且转移出来的数仍相邻,这也意味着里面有一个奇数有一个偶数。因为对奇数满足f(x)=f(x-1)+f(x+1),所以转化后的x/2,x/2-1或x/2,x/2-1中f(x)较大的一定是奇数。那么我们进一步可以发现:对于一个固定的值f(x),f(x-1)有且仅有一对。
现在我们已经知道f(x)=n,我们枚举f(x-1)的值,按上面的式子每次由f(x),f(x-1)转移至f(x/2+1),f(x/2)或f(x/2),f(x/2-1),直至推至x=2,x-1=1,那么因为我们可以知道f(1)=f(2)=1,再回溯回去即可。有点像更相减损法。其实也可以直接辗转相除。
Code
#include<iostream>
#include<cmath>
#include<cstring>
#include<cstdio>
#include<algorithm>
#define ll long long
using namespace std;
const ll mo=998244353,maxn=1e6+5;
ll n,m,i,t,j,k,l,x,y,z,xx,yy,a[maxn],er[maxn];
char ch;
void dg(ll x,ll y){
if (x==1 && y==1){
xx=2;yy=1;return;
}
if (x==y) return;
if (x>y){
ll t=x/y-(x%y==0);
dg(x-y*t,y);
xx=(xx+yy*(er[t]-1)%mo)%mo;yy=yy*er[t]%mo;
}else{
/*dg(x,y%x);
yy=(xx+yy)%mo;xx=xx*2%mo;*/
ll t=y/x-(y%x==0);
dg(x,y-x*t);
yy=(yy+xx*(er[t]-1)%mo)%mo;xx=xx*er[t]%mo;
}
}
void put(ll x){
if (x<10){
ch=x+48;putchar(ch);return;
}
put(x/10);ch=x%10+48;putchar(ch);
}
int main(){
freopen("func.in","r",stdin);freopen("func.out","w",stdout);
scanf("%lld",&n);
er[0]=1;
for (i=1;i<=1e6;i++)er[i]=er[i-1]*2%mo;
for (i=1;i<=n;i++){
xx=yy=0;
dg(n,i);
if (xx) a[++a[0]]=xx;
}
sort(a+1,a+a[0]+1);
for (i=1;i<=a[0];i++)
put(a[i]),putchar('\n');
}