【JZOJ5317】【清华集训2017模拟8.19】func

来源:互联网 发布:js 短路求值 编辑:程序博客网 时间:2024/06/05 20:12

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 longusing 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');}