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

来源:互联网 发布:linux ntp配置文件 编辑:程序博客网 时间:2024/05/21 17:57

题目

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.
0 0