POJ 3090 Visible Lattice Points

来源:互联网 发布:java静态内部类实例化 编辑:程序博客网 时间:2024/04/29 10:33
Time Limit: 1000MS Memory Limit: 65536KTotal Submissions: 5383 Accepted: 3154

Description

A lattice point (xy) in the first quadrant (x and y are integers greater than or equal to 0), other than the origin, is visible from the origin if the line from (0, 0) to (xy) does not pass through any other lattice point. For example, the point (4, 2) is not visible since the line from the origin passes through (2, 1). The figure below shows the points (xy) with 0 ≤ xy ≤ 5 with lines from the origin to the visible points.

Write a program which, given a value for the size, N, computes the number of visible points (xy) with 0 ≤ xy ≤ N.

Input

The first line of input contains a single integer C (1 ≤ C ≤ 1000) which is the number of datasets that follow.

Each dataset consists of a single line of input containing a single integer N (1 ≤ N ≤ 1000), which is the size.

Output

For each dataset, there is to be one line of output consisting of: the dataset number starting at 1, a single space, the size, a single space and the number of visible points for that size.

Sample Input

4245231

Sample Output

1 2 52 4 133 5 214 231 32549

Source

Greater New York 2006

这样找规律的题,不用说肯定先画1x1,2x2,多考虑几个就有思路了。

先考虑只有1×1的时候,三个点,根据图明显看出,只需要计算下三角,结果=下三角的个数×2再加1(斜率为1的点)。

那么我们只需要计算斜率从0到1之间的个数就行了,不包括1,包括0.结果设为sum,那么最终就是2*sum+1.

 

1×1只有一个斜率为0的

2×2斜率有0,1/2(0已经算过了,以后不再算了),其实就多了一个斜率为1/2的。

3×3的时候,有1/3,2/3两个,比以前多了2个

4×4的时候,有1/4,2/4(1/2已经有过了),3/4,所以也是2个

5×5的时候,有1/5,2/5,3/5,4/5,之前都没有,所以多了4个

6×6得到时候,有1/6,2/6(1/3已经有了),3/6(1/2已经有了),4/6(2/3已经有了),5/6,所以只剩2个。


从上面可以发现一个规律,对于n×n,可以从0,0连接到(n,0)到(n,n)上,斜率将会是1/n,2/n......(n-1)/n;

凡是分子和分母能够约分的,也就是有公约数,前面都已经有过了。所以每次添加的个数就是分子和分母互质的个数。

那么问题就转换为,对于一个数n,求小于n的于n互质的数的个数,这不就是欧拉函数么? 

•欧拉函数:
inteuler_phi(int n)
{
    int m=(int)sqrt(n+0.5);
    int ans=n;
    for(int i=2;i<=m;i++)
        if(n%i==0)//找素因子
        {
            ans=ans/i*(i-1);
            while(n%i==0)n/=i;//除尽
        }
    if(n>1)ans=ans/n*(n-1);
returnans;

下面直接套函数就行了。

#include<iostream>using namespace std;int euler_phi(int n){    int m=(int)sqrt(n+0.5);    int ans=n;    for(int i=2;i<=m;i++)        if(n%i==0)//找素因子        {            ans=ans/i*(i-1);            while(n%i==0)n/=i;//除尽        }    if(n>1)      ans=ans/n*(n-1);    return ans;}int main(){    int T,i,r,t,ct;    cin>>T;    t=0;    while(T--)      {           ct=0,t=t+1;          cin>>r;              for(i=2;i<=r;i++)           ct=ct+euler_phi(i);      //冲eluler_phi(2)加到i;          cout<<t<<" "<<r<<" "<<2*ct+3<<endl;//算出来的只是一半(斜率为0,和1的直线一没算进去),所以要乘以2,再加上中间那一条,总共是乘2加3.         // for(i=2;i<250;i++)          //cout<<i<<" "<<euler_phi(i)<<endl;      }    return 0;}










0 0
原创粉丝点击