1. 程式人生 > >51nod1222最小公倍數計數

51nod1222最小公倍數計數

nod 就是 一個 技術 com esp spa lan abc

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

51nod1222最小公倍數計數