Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 4141 Accepted Submission(s): 1441
1 /* 2 题意:区间x属于[1,A] , y属于区间[1,B] 3 求最大公约数是K,即gcd(x,y)=K。 4 并且[1,3]和[3,1]属于同一种情况。 5 6 思路:HDU 4135 Co-prime 的思路在这一题有用。 7 它的题意:区间[A,B],与整数N的互素的个数 8 对于这一到题目:gcd(x,y)=k. 9 要满足最大公约数是K,可以转化为 10 [1,A],[1,B]==>[1,A/K],[1,B/K] 求互素的个数。 11 好像有点难以想到。???? 12 {{ 13 借鉴一下别人是说法。会更明白 14 gcd(x, y) == k 说明x,y都能被k整除,但是能被k整除的未必gcd=k , 15 必须还要满足互质关系. 16 问题就转化为了求1~a/k 和 1~b/k间互质对数的问题 17 }} 18 这样的话,如何处理呢? 19 题意要求[1,3]和[3,1]不能重复。 20 对于区间[1,A/K],[1,B/K] 看成==>[1,a],[1,b] 有几种情况 21 1____________a 22 1____________________b 23 24 25 1____________a 26 1________b 27 28 29 1____________a 30 1____________b 31 32 这三种情况。我们来个判断,总是让a<=b,用b做更大的值。就会变成 33 34 1—————————a 35 1—————————————————b 36 在求取的过程中也是采取这样的规则。 37 [?,b1];确定后一位数。表示在[1,a]中与b1互质的个数。 38 那么就很好的避免了[1,3],[3,1]的情况了。 39 求取总和sum=sum1+sum2; 40 sum1=欧拉函数值[1,a]; 想想为什么? 41 sum2={枚举a+1--->b,与区间[1,a]互质的个数}; 42 sum2就和以前的一题有关系了,要用欧拉函数+容斥定理处理。 43 具体的参考:http://www.cnblogs.com/tom987690183/p/3246197.html 44 45 46 */ 47 48 #include<stdio.h> 49 #include<string.h> 50 #include<stdlib.h> 51 52 53 int prime[100003],len; 54 bool s[100003]; 55 int opl[100003]; 56 int Que[100003]; 57 int f[1000],flen; 58 59 void make_prime() //素数打表 60 { 61 int i,j; 62 len=0; 63 for(i=2;i<=100000;i++)//刚开始写错,i*i<=100000;⊙﹏⊙b汗 64 if(s[i]==false) 65 { 66 prime[++len]=i; 67 for(j=i*2;j<=100000;j=j+i) 68 s[j]=true; 69 } 70 } 71 72 void make_Euler() //欧拉函数打表。 73 { 74 int i,j; 75 make_prime(); 76 for(i=2;i<=100000;i++) 77 opl[i]=i; 78 opl[1]=1; 79 for(i=1;i<=len;i++) 80 for(j=prime[i];j<=100000;j=j+prime[i]) 81 opl[j]=opl[j]/prime[i]*(prime[i]-1); 82 } 83 84 void make_dEuler(int n) //单点欧拉的素因子。 85 { 86 int i; 87 flen=0; 88 for(i=2;i*i<=n;i++) 89 { 90 if(n%i==0) 91 { 92 while(n%i==0) 93 n=n/i; 94 f[++flen]=i; 95 } 96 } 97 if(n!=1) 98 f[++flen]=n; 99 } 100 101 int Capacity(int m) 102 { 103 int i,j,t=0,sum=0,k; 104 Que[t++]=-1; 105 for(i=1;i<=flen;i++) 106 { 107 k=t; 108 for(j=0;j<k;j++) 109 Que[t++]=-1*Que[j]*f[i]; 110 } 111 for(i=1;i<t;i++) 112 sum=sum+m/Que[i]; 113 return sum; 114 } 115 116 117 void sc()//输出函数,测试用的。 118 { 119 int i; 120 for(i=1;i<=10;i++) 121 printf("%d ",opl[i]); 122 printf("\n"); 123 } 124 125 __int64 make_ini(int b,int c,int k) 126 { 127 int i,x,y,tmp; 128 __int64 sum=0; 129 x=b/k;y=c/k;//加特判的用处。不能除0 130 if(x>y) 131 { 132 tmp=x; 133 x=y; 134 y=tmp; 135 } 136 for(i=1;i<=x;i++) 137 sum=sum+opl[i];//第一步 138 for(i=x+1;i<=y;i++)//第二步,枚举 139 { 140 make_dEuler(i); 141 sum=sum+(x-Capacity(x)); 142 } 143 //sc(); 144 return sum; 145 146 } 147 148 int main() 149 { 150 int T,a,b,c,d,k,i; 151 __int64 sum; 152 make_Euler(); 153 while(scanf("%d",&T)>0) 154 { 155 for(i=1;i<=T;i++) 156 { 157 sum=0; 158 scanf("%d%d%d%d%d",&a,&b,&c,&d,&k); 159 if(k==0) //特判,否则会Runtime Error (INTEGER_DIVIDE_BY_ZERO) 160 { 161 sum=0; 162 } 163 else sum=make_ini(b,d,k); 164 printf("Case %d: %I64d\n",i,sum); 165 166 } 167 } 168 return 0; 169 }
1 #include<iostream> 2 #include<stdio.h> 3 #include<cstring> 4 #include<cstdlib> 5 using namespace std; 6 typedef __int64 LL; 7 8 const int maxn = 1e5+3; 9 bool s[maxn]; 10 int prime[maxn],len = 0; 11 int mu[maxn]; 12 int sum1[maxn]; 13 void init() 14 { 15 memset(s,true,sizeof(s)); 16 mu[1] = 1; 17 for(int i=2;i<maxn;i++) 18 { 19 if(s[i] == true) 20 { 21 prime[++len] = i; 22 mu[i] = -1; 23 } 24 for(int j=1;j<=len && (long long)prime[j]*i<maxn;j++) 25 { 26 s[i*prime[j]] = false; 27 if(i%prime[j]!=0) 28 mu[i*prime[j]] = -mu[i]; 29 else 30 { 31 mu[i*prime[j]] = 0; 32 break; 33 } 34 } 35 } 36 for(int i=1;i<maxn;i++) 37 sum1[i] = sum1[i-1]+mu[i]; 38 } 39 LL solve(int a,int b) 40 { 41 LL sum = 0; 42 for(int i=1,la = 0;i<=a;i++,i = la+1) 43 { 44 la = min(a/(a/i),b/(b/i)); //优化部分 45 sum = sum + ((LL)(a/i))*(b/i)*(sum1[la]-sum1[i-1]); 46 } 47 return sum; 48 } 49 int main() 50 { 51 int T,l,a,b,d; 52 init(); 53 scanf("%d",&T); 54 for(int t=1;t<=T;t++) 55 { 56 scanf("%d%d%d%d%d",&l,&a,&l,&b,&d); 57 LL sum = 0 ; 58 if(d==0) ; 59 else{ 60 if(a>b) swap(a,b); 61 sum = solve(a/d,b/d); 62 sum = sum - solve(a/d,a/d)/2; 63 } 64 printf("Case %d: %I64d\n",t,sum); 65 } 66 return 0; 67 }