hdu1695 GCD

    好题
    整理下思路~~
    前面做过一道这样的问题:
    1……N里有多少个数X,满足(X,N)=C
    一种解法是这样的:
    X=x*C,N=n*C,则(x,n)=1
    即求x的个数
    (x,n)=1 && x<=n( x*C<=n*C=N )
    则x的个数即为phi(n)=phi(N/c)
    现在这个问题是这样的:
    X属于1……a,Y属于1……b (不妨设a<=b)
    求解数对X,Y的个数,满足(X,Y)=C
    我的解法是这样的:
    X=x*C,Y=y*C,(x,y)=1
    枚举x,对于一个特定的x,y满足:
    (x,y)=1;
    x<=y;
    y<=b/C ( y*C=Y<=b )
    对x分解素因子,然后在区间[x,b/C]里利用容斥原理求解
    写着写着发现,如果枚举y,那么x满足
    (x,y)=1
    x<=y
    x*C=X<=a,x<=a/C
    则
    对于y<=a/C,x满足 (x,y)=1 && x<=y 即为phi(y)
    对于y>a/C, x满足 (x,y)=1 && x<=a/C,还是利用容斥原理求解
    本来想试着只用欧拉函数解决,没成功,这样的话应该没快多少。。。

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<cmath>
 4 #include<algorithm>
 5 using namespace std;
 6 typedef long long LL;
 7 const int maxp = 15,maxn = 100000;
 8 
 9 int p[maxp],pk;
10 int prime[maxn+5],pd[maxn+5],pnum;
11 
12 void gp()
13 {
14     for(int i=2;i<=maxn;i++)
15     {
16         if( !pd[i] )    prime[++pnum]=pd[i]=i;
17         for(int j=1;j<=pnum && prime[j]<=maxn/i;j++)
18         {
19             pd[i*prime[j]]=prime[j];
20             if( i%prime[j]==0 ) break;
21         }
22     }
23 }
24 
25 void fenjie(int n)
26 {
27     pk=0;
28     while( n>1 )
29     {
30         int d=pd[n];
31         p[++pk]=d;
32         while( n%d==0 ) n/=d;
33     }
34 }
35 
36 void rc(int idx,int cur,int c,int n,bool flag,LL& ans)
37 {
38     int tmp;
39     for(int i=idx;i<=pk;i++)
40     {
41         tmp=cur*p[i];
42         if( flag )  ans+=n/tmp-c/tmp;
43         else ans-=n/tmp-c/tmp;
44         rc(i+1,tmp,c,n,!flag,ans);
45     }
46 }
47 
48 int main()
49 {
50     gp();
51     int T,a,b,c,d,k;
52 
53     scanf("%d",&T);
54     for(int cs=1;cs<=T;cs++)
55     {
56         scanf("%d%d%d%d%d",&a,&b,&c,&d,&k);
57         a=b;b=d;
58         printf("Case %d: ",cs);
59         if( !k || k>a || k>b )    {puts("0");continue;}
60         if( a>b )   swap(a,b);
61         LL ans=b/k,tmp;
62         for(int i=2;i*k<=a;i++)
63         {
64             fenjie(i);
65             tmp=0;
66             rc(1,1,i-1,b/k,true,tmp);
67             ans+=b/k-i+1-tmp;
68         }
69         printf("%I64d\n",ans);
70     }
71     return 0;
72 }
View Code

 

posted @ 2013-05-25 21:55  kiwi_bird  阅读(121)  评论(0编辑  收藏  举报