BZOJ2190 SDOI2008 仪仗队

flag:数论,欧拉函数。

          http://www.lydsy.com/JudgeOnline/problem.php?id=2190

PS:我们发现当x1=k*x

                  y1=k*y时

                 此刻正能看见一个

 

于是又GCD(X1,Y1)>=2是只能看到一个==》等价于

GCD(X1,Y1)=1;

我们想到:

{盗图}

这个公式,因为其实点在(1,1) 所以需要n-1,n-1;

然后这个公式等于

的两倍-1

因为(1,1)算了两次

 

于是有了:筛法求phi;

再求和;

code:

   

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cmath>
 4 #include <cstdlib>
 5 #include <algorithm>
 6 #include <cstring>
 7 #define ll long long
 8 #define ull unsigned long long
 9 
10 using namespace std;
11 
12 bool f[40001];
13 ull p[40001];
14 ull ans[40001];
15 
16 int main()
17 {
18     int n,tot=0;
19     cin >>n;
20     if (n<=1){
21         cout <<0 <<endl;
22         return 0;
23         }
24 
25         memset(f,false,sizeof(f));
26         f[1]=true;
27         for (int i=2;i<=n;i++){
28         if (!f[i]){
29             p[++tot]=i;
30             ans[i]=i-1;
31         }
32 
33         for (int j=1;j<=tot&&i*p[j]<=n;j++)
34         {
35             f[i*p[j]]=1;
36             if (i%p[j]==0)
37             {
38                 ans[i*p[j]]=ans[i]*p[j];
39                 break;
40             }
41             else ans[i*p[j]]=ans[i]*(p[j]-1);
42         }
43 
44         for (int j=1;(j<=tot)&&(i*p[j]<=n);j++){
45             f[i*p[j]]=true;
46             if (i%p[j]==0){
47                     ans[i*p[j]]=ans[i]*p[j];
48                     break;
49             }
50             else{
51                 ans[i*p[j]]=ans[i]*(p[j]-1);
52             }
53         }
54     }
55 
57     long long pr=2;
58     for (int i=2;i<=n-1;i++) pr+=ans[i];
59     cout <<pr*2-1 <<endl;
60     return 0;
61 }

贴TMP 吧

 

posted on 2015-04-21 00:41  forgot93  阅读(205)  评论(0编辑  收藏  举报

导航