• 周四. 4 月 23rd, 2026

物嫩软件资讯网

软件资讯来物嫩

XDOJ1210 – 射击游戏

admin@wunen

5 月 7, 2025


Description

zjy非常喜欢射击游戏,而且技术相当好,百发百中。@_@!

这次,他站在坐标系的(0,0)点。靶子位于格点(x,y)上,0 <= x <= n,0 <= y <= n,x,y均为整数。由于子弹不能穿过靶子( -_-! ) ,所以他不能打到被其他靶子遮住的靶子。上图显示了区域0 <= x <= 3, 0 <= y <= 3内的靶子(红点),以及zjy可以打得到的靶子。

给出n,计算区域0 <= x <= n, 0 <= y <= n内,zjy可以打到的靶子数目。


Input

多组数据,以-1结束。

每组数据一行,每行一个整数n(1 <= n <= 500000),表示区域的大小。


Output

输出一个整数,表示zjy可以打得到的靶子数目。


Sample Input

3

4

5

-1


Sample Output

9

13

21


Hint

结果不保证在32位之内,建议使用long long或I64d


解题思路:

简单数论题。设能打到的靶子为(x,y),则x,y必然互素。打表生成1…n内的欧拉函数,并求和sum=∑phi(i),1<=i<=n。(x,y)和(y,x)为两个不同的点,所以结果就是2*sum,考虑到(1,1)只有一个还要加上(1,0),(0,1)两个点,所以ans=2*sum+1 。

还要注意的是,要用生成素数的方法生成欧拉函数,否则会超时

#include<iostream>
#include<cmath>
using namespace std;
const int D = 500000;
int phi[D];

void init()
{
    for(int i=1;i<=D;++i)
        phi[i] = i;
    for(int i=2;i<=D;i+=2)
        phi[i] /= 2;
    for(int i=3;i<=D;i+=2)
        if(phi[i]==i)
        {
            for(int j=i;j<=D;j+=i)
                phi[j] = phi[j]/i*(i-1);
        }

}
int main()
{
    long long n;
    init();
    while(cin>>n)
    {
        if(n==-1)
            break;
        long long ans = 0;
        for(int i=0;i<n;++i)
            ans += phi[i+1];
        cout<<2*ans+1<<endl;
    }
    return 0;
}

最后欢迎大家访问我的个人网站:

1024s

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注