天天看點

JZOJ 3509. 【NOIP2013模拟11.5B組】倒黴的小C

3509. 【NOIP2013模拟11.5B組】倒黴的小C(beats) 

(File IO): input:beats.in output:beats.out

Time Limits:  1000 ms  Memory Limits: 262144 KB  Detailed Limits   Goto ProblemSet

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      

  做法:

通過簡單觀察可以發現,每次畫出向量(n,i)經過的格點個數為gcd(i,n),那麼答案就等于Ans=1+

JZOJ 3509. 【NOIP2013模拟11.5B組】倒黴的小C

直接求解的時間複雜度是O(n)的。

那麼Ans=1+

JZOJ 3509. 【NOIP2013模拟11.5B組】倒黴的小C

其中d為n的約數。fai(n)表示1~n中與n互質的數的個數。通過這樣的變形,我們就可以得到時間複雜度為O(C*sqrt(n))的算法,C為n的約數個數。

代碼如下:

1 #include <cstdio>
 2 #include <iostream>
 3 #include <string>
 4 #include <cstring>
 5 #include <cmath>
 6 #define LL long long
 7 using namespace std;
 8 LL n, ans, k;
 9 
10 LL phi(LL x)
11 {
12     LL k = x;
13     for (int i = 2; x > 1; i++)
14         if (x % i == 0)
15         {
16             k -= k / i;
17             while (x % i == 0)    x /= i;    
18         }
19     return k;
20 }
21 
22 int main()
23 {
24     freopen("beats.in", "r", stdin);
25     freopen("beats.out", "w", stdout);
26     cin >> n;
27     int p = sqrt(n);
28     for (int i = 1; i <= p; i++)
29         if (n % i == 0)
30         {
31             k = i;
32             ans += k * phi(n / k);
33             if (k != n / k)    k = n / i, ans += k * phi(n / k);
34         }
35     cout << ans + 1;
36     return 0;
37 }      

View Code

轉載于:https://www.cnblogs.com/traveller-ly/p/9338603.html