【NOIP2017提高组模拟12.10】幻魔皇

本文探讨了在深度为n的斐波那契树中寻找特定白色节点对的问题,介绍了如何计算不同距离下节点对的数量,并通过数学推导给出了解决方案。文章还分享了一段使用线性筛法的Pascal代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目

Description

幻魔皇拉比艾尔很喜欢斐波那契树,他想找到神奇的节点对。
所谓斐波那契树,根是一个白色节点,每个白色节点都有一个黑色节点儿子,而每个黑色节点则有一个白色和一个黑色节点儿子。神奇的节点对则是指白色节点对。
请问对于深度为n的斐波那契树,其中距离为i的神奇节点对有多少个?拉比艾尔需要你对于1<=i<=2n的所有i都求出答案。

Input

一行一个正整数n。

Output

一行2n个整数表示答案,对123456789取模。

Sample Input

5

Sample Output

0 2 3 3 1 1 0 0 0 0

Data Constraint

对于20%的数据n<=10;
对于40%的数据n<=20;
对于60%的数据n<=30;
对于80%的数据n<=400;
对于100%的数据n<=5000。

题解

我们设gcd(a,b)=d
a=a’*d,b=b’ *d
则如果要满足题目中的条件,就要满足d(a+b)|ddab,然后因为a’和b’是互质的,所以我们有:gcd(a’+b’,a’*b’)=1,则:(a+b)|d
我们设k(a+b)=d,根据题意中a+b<=n可得:d(a+b)<=n,将两式子结合,得:
k(a+b)2<=n,移项之后:k<=n/(a+b)2,那么这个值就是可以取的d的个数(不可以直接将d(a+b)<=n移项,以为还要满足(a+b)|d

那么我们可以枚举d(1,n],那么对于一个确定的k,可能的对数就为ϕ(d)n/d2
这是为什么呢?
首先对于一个确定的d我们可以取的k一共有n/d2种,然后就是对于每一个k,如果一对数a,b合法,那么就有1:a+b=d ,2:gcd(a,b)=1
由2得:gcd(b,a+b)=1,即gcd(b,d)=1
所以是ϕ(d)
然后我们发现如果d>n,那么上述的值就为0
所以最终复杂度:n

关于线性筛

由于本人以前比较弱,不会证明线筛,现在打一下证明
首先我们每遇到一个质数,就把它加进一个存质数的数组中
然后发现i*p[j]一定是一个合数
乍一看这样会超时
但是一条神奇的语句:if i mod p[j]=0 then break让这个东西变成了O(N)
我们设1:i*p[j]=p,2:i’ *p[j’]=p,且j<j
然后如果这样做对于每一个合数只会被最小的一个p[j]筛掉
因为较大的其他的都会被break掉

贴代码

var
    p:array[0..10000005]of longint;
    ol:array[0..10000005]of int64;
    bz:array[0..10000005]of boolean;
    i,j,n:longint;
    x,y,m,ans:int64;
begin
    assign(input,'uria.in'); reset(input);
    assign(output,'uria.out'); rewrite(output);
    readln(m);
    n:=trunc(sqrt(m));
    for i:=2 to n do
    begin
        if bz[i]=false then
        begin
            ol[i]:=i-1;
            inc(p[0]);
            p[p[0]]:=i;
        end;
        for j:=1 to p[0] do
        begin
            if (i*p[j]>n)then break;
            bz[i*p[j]]:=true;
            if i mod p[j]=0 then ol[i*p[j]]:=ol[i]*p[j]
            else ol[i*p[j]]:=ol[i]*(p[j]-1);
            if i mod p[j]=0 then break;
        end;
    end;
    for i:=2 to n do ans:=ans+((m div i) div i)*ol[i];
    writeln(ans);
    close(input); close(output);
end.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值