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

32 篇文章 0 订阅

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');
} 
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值