打表

来源:互联网 发布:成都广电网络 编辑:程序博客网 时间:2024/05/08 12:57

【题目描述】
kkk参加了NOI2333,结果被虐爆了!最简单的题目要求输入两个整数x和y,输出一个函数f(x,y)=F[x^y]^F[x]^F[y](F[i]代表斐波那契数列的第i项),而且x和y都在1到N(N是给定的数)以内!kkk急的抓耳挠腮,于是只好交表。但是比赛有代码长度限制!这么大的表无法提交(怎么打出来都是个问题)!所以kkk只能删掉一些表(而且删掉所有换行)以缩短代码。
但是kkk发现,这道题目可以根据f(x,y)用O(1)的算法算出f(x*k,y*k),其中k是任意正整数。别管这个规律是kkk是肿么发现的,也别管它对不对(肯定不对嘛),只要你——lzn——kkk的作弊帮手知道就可以了。所以,某些f函数是没有必要保存的,需要时调出其他的f函数计算下就可以了。
给出N,你需要求出最短的表里有多少个元素。
【输入格式】
有多组数据,每组数据包含一个整数N
【输出格式】
对于每组数据输出元素个数
【样例输入】
2
5
【样例输出】
3
19
【数据范围】
1<=N<=50000
【分析】
不难看出此题可以简化为:给出N,求有多少组(x,y)满足1<=x,y<=n且x和y互质。
可以发现,除了(1,1)外,其他的(x,y)都不相等。于是设满足x<=y-1的情况有f[n]个,则答案就是2*f[n]+1。
这里引入欧拉phi函数。
于是可以知道,这里写图片描述

const  maxn=50000;var  phi,psum:array[0..maxn+1]of longint;    i,n:longint;procedure table(n:longint);var  i,j:longint;begin  phi[1]:=0;    for i:=2 to n do      if phi[i]=0 then begin          j:=i;          while j<=n do begin              if phi[j]=0 then phi[j]:=j;                phi[j]:=phi[j] div i*(i-1);              j:=j+i;            end;        end;end;begin  table(maxn);    psum[0]:=0;    for i:=1 to maxn do psum[i]:=psum[i-1]+phi[i];    readln(n);    writeln(2*psum[n]+1);end.
3 0