51nod1222最小公倍数计数

51nod1222

http://210.33.19.103/contest/1113/problem/2

同学的神仙做法:

首先考虑先去掉X<=Y的限制,也就是先计算满足要求的任意有序pair(X,Y)的数量,再用一些简单操作(略去)得到目标答案

化简式子可以得到$\sum_{d}\mu(d)\sum_a\sum_b\sum_c[abc<={\lfloor}\frac{n}{d^2}{\rfloor}]$

可以强行给a,b,c规定一个顺序。设a是最小的,则a只需要枚举到$(\frac{n}{d^2})^{1/3}$就行

剩下有很多做法了,略去了

 1 %:pragma GCC optimize(2)
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<cstring>
 5 #include<vector>
 6 #include<cmath>
 7 using namespace std;
 8 #define fi first
 9 #define se second
10 #define mp make_pair
11 #define pb push_back
12 typedef long long ll;
13 typedef unsigned long long ull;
14 int mu[400001];
15 int prime[100011],len;
16 bool nprime[400001];
17 /*
18 ll calc0(ll n)
19 {
20     ll d,i,j,k,tan1,tan2,tan3,t1;
21     for(d=1;;++d)
22     {
23         if(d*d>n)    break;
24         t1=n/(d*d);
25         tan1=tan2=tan3=0;
26         for(i=1;i<=100;++i)
27             for(j=1;j<=100;++j)
28                 for(k=1;k<=100;++k)
29                     if(i*j*k<=t1)
30                         if(i==j&&j==k)
31                             ++tan3;
32                         else if(i==j||j==k||i==k)
33                             ++tan2;
34                         else ++tan1;
35         printf("at%lld %lld %lld\n",tan1,tan2,tan3);
36     }
37     return 233;
38 }
39 */
40 ll calc(ll n)
41 {
42     ll d,t1,t2,endj,i,j,j1,tan1,tan2,tan3,ans=0,endi;
43     for(d=1;;++d)
44         if(mu[d])
45         {
46             if(d*d>n)    break;
47             t1=n/(d*d);
48             tan1=tan2=tan3=0;
49             for(i=1;;++i)
50             {
51                 if(i*i*i>t1)    break;
52                 t2=t1/i;
53                 endj=ll(sqrt(t2+0.5));
54                 for(j=i+1;j<=endj;j=j1+1)
55                 {
56                     j1=min(endj,t2/(t2/j));
57                     tan1+=(t2/j)*(j1-j+1);
58                 }
59                 if(i+1<=endj)
60                     tan1-=(endj+i+1)*(endj-i)/2;
61             }
62             tan1*=6;
63             endi=ll(sqrt(t1+0.5));
64             for(i=1;i<=endi;++i)
65                 tan2+=t1/(i*i);
66             for(i=1;;++i)
67             {
68                 if(i*i*i>t1)    break;
69                 ++tan3;
70             }
71             tan2=(tan2-tan3)*3;    
72             ans+=mu[d]*(tan1+tan2+tan3);
73             //printf("1t%lld %lld %lld %lld\n",d,tan1,tan2,tan3);
74         }
75     return ans;
76 }
77 int main()
78 {
79     ll i,j,t;
80     mu[1]=1;
81     for(i=2;i<=400000;i++)
82     {
83         if(!nprime[i])    prime[++len]=i,mu[i]=-1;
84         for(j=1;j<=len&&(t=i*prime[j])<=400000;j++)
85         {
86             nprime[t]=1;
87             if(i%prime[j]==0)    {mu[t]=0;break;}
88             else    mu[t]=-mu[i];
89         }
90     }
91     ll a,b;
92     scanf("%lld%lld",&a,&b);
93     printf("%lld\n",(calc(b)-calc(a-1)+b-a+1)/2);
94     //calc0(b);calc0(a-1);
95     return 0;
96 }
View Code

 

posted @ 2019-02-26 19:20  hehe_54321  阅读(153)  评论(0编辑  收藏  举报
AmazingCounters.com