# bzoj4652 [Noi2016]循环之美

2 6 10

## Sample Output

4
explanation

1/1=1.0000……
1/3=0.3333……
2/1=2.0000……
2/3=0.6666……
1/1 和 2/2 虽然都是纯循环小数，但因为它们相等，因此只计数一次；同样，1/3 和 2/6 也只计数一次。

24分暴力：

 1 //It is made by wfj_2048~
2 #include <algorithm>
3 #include <iostream>
4 #include <complex>
5 #include <cstring>
6 #include <cstdlib>
7 #include <cstdio>
8 #include <vector>
9 #include <cmath>
10 #include <queue>
11 #include <stack>
12 #include <map>
13 #include <set>
14 #define inf (1<<30)
15 #define il inline
16 #define RG register
17 #define ll long long
18
19 using namespace std;
20
21 int n,m,k,ans;
22
23 il int gi(){
24     RG int x=0,q=1; RG char ch=getchar(); while ((ch<'0' || ch>'9') && ch!='-') ch=getchar();
25     if (ch=='-') q=-1,ch=getchar(); while (ch>='0' && ch<='9') x=x*10+ch-48,ch=getchar(); return q*x;
26 }
27
28 il int gcd(RG int a,RG int b){ return b ? gcd(b,a%b) : a; }
29
30 il void work(){
31     n=gi(),m=gi(),k=gi();
32     for (RG int i=1;i<=m;++i){
33     if (gcd(i,k)!=1) continue;
34     for (RG int j=1;j<=n;++j) if (gcd(i,j)==1) ans++;
35     }
36     printf("%d\n",ans); return;
37 }
38
39 int main(){
40     work();
41     return 0;
42 }

$Ans=\sum_{i=1}^{m}[\gcd(i,k)==1]\sum_{j=1}^{n}[\gcd(i,j)==1]$

$Ans=\sum_{i=1}^{m}[gcd(i,k)==1]\sum_{j=1}^{n}\sum_{d|i,d|j}\mu(d)$

$Ans=\sum_{i=1}^{m}[\gcd(i,k)==1]\sum_{d|i}^{n}\mu(d)\left \lfloor \frac{n}{d} \right \rfloor$

$Ans=\sum_{d=1}^{min(n,m)} \mu(d)\left \lfloor \frac{n}{d} \right \rfloor \sum_{i=1}^{\frac{m}{d}} [\gcd(i*d,k)==1]$

$Ans=\sum_{d=1}^{min(n,m)} [\gcd(d,k)==1]\mu(d)\left \lfloor \frac{n}{d} \right \rfloor \sum_{i=1}^{\frac{m}{d}} [\gcd(i,k)==1]$

84分暴力：

 1 //It is made by wfj_2048~
2 #include <algorithm>
3 #include <iostream>
4 #include <complex>
5 #include <cstring>
6 #include <cstdlib>
7 #include <cstdio>
8 #include <vector>
9 #include <cmath>
10 #include <queue>
11 #include <stack>
12 #include <map>
13 #include <set>
14 #define inf (1<<30)
15 #define N (20000010)
16 #define il inline
17 #define RG register
18 #define ll long long
19
20 using namespace std;
21
22 int f[2010],vis[N],mu[N],prime[N],n,m,k,nn,cnt;
23 ll ans;
24
25 il int gi(){
26     RG int x=0,q=1; RG char ch=getchar(); while ((ch<'0' || ch>'9') && ch!='-') ch=getchar();
27     if (ch=='-') q=-1,ch=getchar(); while (ch>='0' && ch<='9') x=x*10+ch-48,ch=getchar(); return q*x;
28 }
29
30 il int gcd(RG int a,RG int b){ return b ? gcd(b,a%b) : a; }
31
32 il void pre(){
33     vis[1]=mu[1]=1;
34     for (RG int i=2;i<=nn;++i){
35     if (!vis[i]) mu[i]=-1,prime[++cnt]=i;
36     for (RG int j=1,k=i*prime[j];j<=cnt && k<=nn;++j,k=i*prime[j]){
37         vis[k]=1; if (i%prime[j]) mu[k]=-mu[i]; else break;
38     }
39     }
40     for (RG int i=1;i<=k;++i) f[i]=f[i-1]+(gcd(i,k)==1); return;
41 }
42
43 il void work(){
44     n=gi(),m=gi(),k=gi(),nn=min(n,m); pre();
45     for (RG int d=1;d<=nn;++d){
46     if (gcd(d,k)!=1) continue;
47     ans+=(ll)mu[d]*(ll)(n/d)*(ll)((ll)(m/d/k)*(ll)f[k]+(ll)f[m/d%k]);
48     }
49     printf("%lld\n",ans); return;
50 }
51
52 int main(){
53     work();
54     return 0;
55 }

100分：

\begin{aligned} g(n,k)&=g(n,q)- \sum_{y=1}^{\lfloor\frac{n}{p}\rfloor}[y\perp p][y\perp q]\mu(p)\mu(y)\\&=g(n,q)-\mu(p)\sum_{y=1}^{\lfloor\frac{n}{p}\rfloor}[y\perp k]\mu(y)\\&=g(n,q)+g(\lfloor\frac{n}{p}\rfloor,k) \end{aligned}

 1 //It is made by wfj_2048~
2 #include <algorithm>
3 #include <iostream>
4 #include <complex>
5 #include <cstring>
6 #include <cstdlib>
7 #include <cstdio>
8 #include <vector>
9 #include <cmath>
10 #include <queue>
11 #include <stack>
12 #include <map>
13 #include <set>
14 #define inf (1<<30)
15 #define N (5000010)
16 #define il inline
17 #define RG register
18 #define ll long long
19 #define calc(x) ( (x/k)*f[k]+f[x%k] )
20
21 using namespace std;
22
23 map <ll,map<ll,ll> >gg;
24 map <ll,ll> ff;
25
26 ll f[2010],di[2010],vis[N],mu[N],prime[N],n,m,k,nn,NN,pos,cnt,kcnt,ans;
27
28 il ll gi(){
29     RG ll x=0,q=1; RG char ch=getchar(); while ((ch<'0' || ch>'9') && ch!='-') ch=getchar();
30     if (ch=='-') q=-1,ch=getchar(); while (ch>='0' && ch<='9') x=x*10+ch-48,ch=getchar(); return q*x;
31 }
32
33 il ll gcd(RG ll a,RG ll b){ return b ? gcd(b,a%b) : a; }
34
35 il void pre(){
36     vis[1]=mu[1]=1; RG ll kk=k;
37     for (RG ll i=2;i<=nn;++i){
38     if (!vis[i]) mu[i]=-1,prime[++cnt]=i;
39     for (RG ll j=1,k=i*prime[j];j<=cnt && k<=nn;++j,k=i*prime[j]){
40         vis[k]=1; if (i%prime[j]) mu[k]=-mu[i]; else break;
41     }
42     }
43     for (RG ll i=2;i<=k;++i){
44     if (!(kk%i)) di[++kcnt]=i;
45     while (!(kk%i)) kk/=i;
46     }
47     for (RG ll i=1;i<=k;++i) f[i]=f[i-1]+(gcd(i,k)==1);
48     for (RG ll i=2;i<=nn;++i) mu[i]+=mu[i-1]; return;
49 }
50
51 il ll du(RG ll x){
52     if (x<=nn) return mu[x];
53     if (ff[x]) return ff[x];
54     RG ll ans=1,pos;
55     for (RG ll i=2;i<=x;i=pos+1)
56     pos=x/(x/i),ans-=(pos-i+1)*du(x/i);
57     return ff[x]=ans;
58 }
59
60 il ll g(RG ll x,RG ll y){
61     if (x<=1) return x;
62     if (!y) return du(x);
63     if (gg[x][y]) return gg[x][y];
64     return gg[x][y]=g(x,y-1)+g(x/di[y],y);
65 }
66
67 il void work(){
68     n=gi(),m=gi(),k=gi(); NN=min(n,m);
69     nn=min(NN,5000000LL); pre();
70     for (RG ll d=1;d<=NN;d=pos+1){
71     pos=min(n/(n/d),m/(m/d));
72     ans+=(g(pos,kcnt)-g(d-1,kcnt))*(ll)(n/d)*(ll)calc(m/d);
73     }
74     printf("%lld\n",ans); return;
75 }
76
77 int main(){
78     work();
79     return 0;
80 }

posted @ 2017-03-24 14:56  wfj_2048  阅读(734)  评论(2编辑  收藏  举报