您的位置:首页 > 其它

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

2016-12-12 22:12 260 查看

题目

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′)|d∗d∗a′∗b′,然后因为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.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: