[JZOJ3509] 倒霉的小C

Description

  小G最近迷上了岛国动漫《Angel Beats》,她为了画出一个更霸气的Angel Beats的logo,想了如下办法:

  从(0,0)开始,画到(n,1),再从(n,1),画到(2*n,-1),再到(3*n,2),再到(4*n,-2),依此类推,即每次画出一个(n,(-1)^(i+1)*i)的向量,一共画出n个这样的向量。现在小G想让小C求出这个图形穿过了多少格点(坐标都是整数)。

  由于小C想要认真地听他的数学课并且想自己在接力赛中因RP暴光而发生接力棒传错这类的糗事,所以这个问题就交给你啦。小G说,如果连你也解决不好,就把你的RP也吸光。

Input

  输入文件中仅一行为一个整数n。

Output

  输出文件中仅一行为一个数,表示穿过的格点数。

Sample Input

4

Sample Output

9

Data Constraint

  对于20%的数据,满足:n<=100;

  对于40%的数据,满足:n<=10^5;

  对于60%的数据,满足:n<=10^7;

  对于100%的数据,满足:n<=10^10。

Summary

  

  可以发现,每次向量经过的格点个数为gcd(i,n),那么答案就等于Ans=1+=1+

 1 #include<cstdio>
 2 #include<cmath>
 3 using namespace std;
 4 long long ans,m;
 5 long long find(long long x)
 6 {
 7     long long sum=x,i=1;
 8     while (x>1)
 9     {
10         i++;
11         if (x%i==0)
12         {
13             sum-=sum/i;
14             while (x%i==0)
15                 x=x/i;
16         }
17     }
18     return sum;
19 }
20 int main()
21 {
22     scanf("%lld",&m);
23     ans=1;
24     for (long long i=1;i<=(long long)sqrt((double) m);i++)
25         if (m%i==0)
26         {
27             ans=ans+i*find(m/i);
28             if (i*i!=m) 
29                 ans=ans+m/i*find(i);
30         }
31     printf("%lld",ans);
32 }
View Code

 

 

 
posted @ 2018-07-19 07:45  kasiruto  阅读(173)  评论(0编辑  收藏  举报