KeepCode 4 解题报告

  解题报告转摘录自: jian1573

  原文链接:http://www.cnblogs.com/jian1573/archive/2013/01/11/2857010.html

 

ID Origin Title
Problem A HDU 1787 A
Problem B HDU 1695 B
Problem C HDU 4279 C
Problem D HDU 1395 D
Problem E HDU 1262 E
Problem F HDU 1576 F

 

Problem A

   红果果的欧拉函数;

View Code
View Code 

 #include <iostream>   

 using namespace std;  

 //  x=p1^e1*p2^e2~~~pn^en 

 //phi(x)=(p1-1)*p1^(e1-1)*(p2-1)*p2^(e2-1)~~~(pn-1)*pn^(en-1)

 int phi(int m)  

 {  

     int i,s=1;  

     for(i=2;i*i<=m;i++)  {  

         if(m%i==0){  

             m/=i;  

             s*=i-1;  

             while(m%i==0) {  

                 m/=i;  

                 s*=i;  

             }  

         }  

     }  

     if(m>1)  

         s*=m-1;  

     return s;  

 }  

 int main()  

 {  

     int m;  

     while(cin>>m && m)

         cout<<m-1-phi(m)<<endl;  

     return 0;  

 }

 

Problem B

  

  题意: 在1~a, 1~b中挑出(x,y)满足gcd(x,y) = k , 求(x,y) 的对数 , a,b<=10^5

  思路: gcd(x, y) == k 说明x,y都能被k整除. 问题就可以转化为了求1~a/k 和 1~b/k间互质对数的问题;

  我们让b>=a; 然后在[1....b/k]进行枚举,对于每一个i,我们只要在1...min(i-1,a)中找到与i互质数,记录个数,然后累加就得到结果了;

  当i<=a/k时,我们可以直接用欧拉函数计算出与i互质的个数;

  当i>a/k时,先将i质因数分解,求得[1,2,...,b/k] 里所有能被x的质因数整除的数的个数,即不互质的数的个数,然后用b/k减去即可;

   而 我们枚举i的质因数利用容斥原理, 容斥原理的具体如下:

  区间中与i不互质的个数 = (区间中i的每个质因数的倍数个数)-(区间中i的每两个质因数乘积的倍数)+(区间中i的每3个质因数的成绩的倍数个数)-(区间中i的每4个质因数的乘积)+...

参考代码

View Code
View Code 

 #include<iostream>

 #include <cstdio>

 using namespace std;

 const int Max=100005;

 __int64 elur[Max];//存放每个数的欧拉函数值

 int num[Max];//存放数的素因子个数

 int p[Max][20];//存放数的素因子

 void init()//筛选法得到数的素因子及每个数的欧拉函数值

 {

     elur[1]=1;

     for(int i=2;i<Max;i++)

     {

         if(!elur[i])

         {

             for(int j=i;j<Max;j+=i)

             {

                 if(!elur[j])

                     elur[j]=j;

                 elur[j]=elur[j]*(i-1)/i;

                 p[j][num[j]++]=i;

             }

         }

         elur[i]+=elur[i-1]; //进行累加(法里数列长度)

     }

 }

 int dfs(int idx,int b,int now)//求不大于b的数中,与now不互质的数的个数;

 {                                //dfs()写的容斥原理

     int ans=0;

     for(int i=idx;i<num[now];i++)//容斥原理来求A1并A2并A3.....并Ak的元素的数的个数.

         ans += b/p[now][i]-dfs(i+1,b/p[now][i],now);

     return ans;

 }

 

 int main()

 {

     int t,a,b,c,d,k;

     init();

     scanf("%d",&t);

     for(int ca=1;ca<=t;ca++)

     {

         scanf("%d%d%d%d%d",&a,&b,&c,&d,&k);

         printf("Case %d: ",ca);

         if(k==0)

         {

             printf("0\n");

             continue;

         }

         if(b>d)

             swap(b,d);

         b/=k;  d/=k;

         __int64 ans=elur[b];

         for(int i=b+1;i<=d;i++)

             ans+=b-dfs(0,b,i);//求不大于b的数中,与i不互质的数的个数

         printf("%I64d\n",ans);

     }

     return 0;

 }

 

Problem C

  题意  

  :给定一个数N, 在[1,N)中的数M, gcd( M, N ) != 1, 且N%M !=  0; 那么M就为N的一个special number, f( x ) 为统计 x 的special number的个数, 如果f( x )为奇数,那么x就为一个 real numbers. 求给定区间的real number数.

  思路:

  先看f(x),由题意得f(x)=x-phi( x ) - g(x)+1;(  phi(x)为欧拉函数, g(x)为因子个数, +1 是因为1在phi(x)和g(x)中都算了 );

  而real number只与f(x)的机偶性有关所以我们只讨论phi(x)和g(x)的奇偶性;

  我们知道当x>2时phi(x)为偶数;

  g(x)约数个数,我们由基本定理可得,x=p1^e1*p2^e2*…pn^en,而由计数方法易知 x的约数个数为 g(x)=(e1+1)*(e2+1)*…(en+1)的;

  所以若要使 g(x) 为奇数,充要条件是(ei+1)都为奇数,即质数的幂都为偶数。所以此时 x必然是一个平方数;

  综上,x为平方数,其约数个数为奇数;x为非平方数,其约数个数为偶数;

  所以,当x>2时, 若x为平方数,f(x)=x-奇-偶+1,要使f(x)为奇数,则x必为奇数;若x为非平方数,f(x)=x-偶-偶+1,

  要使f(x)为奇数,则x必为偶数。 当x=1或2时,f(x)=0.

  综上,real numbers F(x) 的值为[3,x]中,奇数平方数+偶数非平方数的个数和,即 偶数个数-偶数^2的个数+奇数^2的个数。

  而偶数个数为 x/2-1,-1是为了把2减掉。偶数^2个数为 sqrt(x)/2,奇数^2个数为 ( sqrt(x)-(sqrt(x)/2) )-1,

  这里-1是为了把1减掉。所以,化简后,F(x) = x/2-1+(sqrt(x)%2? 0: -1).

解题代码

View Code
View Code 

 #include<stdio.h>

 #include<string.h>

 #include<stdlib.h>

 #include<math.h>

 

 __int64 get(__int64 x)

 {

     if(x<=2) return 0;

     return x/2-1+( (__int64)sqrt(1.0*x) %2? 0: -1);        

 }

 

 int main()

 {

     int T;

     scanf( "%d", &T );

     while(T--)

     {

         __int64 a, b;

         scanf("%I64d%I64d", &a, &b);

         printf("%I64d\n", get(b)-get(a-1));

     }

 }

 

Problem D

  

  思路: 由题意得N=2^x(x>=1)为偶数, 所以当 n 也为偶数时  N%n必为偶数, 故不存在;

  当n为奇数时,利用同余定理求;

参考代码

View Code
View Code 

 #include <iostream>

 #include <cstdio>

 #include <string>

 #include <cstring>

 #include <cmath>

 using namespace std;

 

 int main( )

 {

     int N;

     while( scanf( "%d", &N )!= EOF ){

         if( N==1 || !(N&1) )

             printf( "2^? mod %d = 1\n", N );

         else{

             int t=2, ans=1;

             while( t != 1 ){

                 t <<= 1;

                 t%=N;

                 ans++;

             } 

             printf( "2^%d mod %d = 1\n",ans, N );

             

         }

     }

     return 0;

 }

 

Problem E

View Code
View Code 

 #include <stdio.h>

 #include <stdlib.h>

 #include <math.h>

 int a[10005]={0};

 void fun(  )

 {

     a[1]=a[0]=1;

     for( int i=4; i<10005; i+=2 )

         a[i]=1;

     for( int i=3; i <= ( int )sqrt( 10005 ); i+=2 )

     {

         if(a[i]==0)

             for( int j=i*i; j<10005; j += ( i+i ) )    

             {

                 a[j]=1;    

             }

     }      

 }

 

 int main()

 {

     fun( );

     int n;

     while( scanf( "%d", &n ) != EOF )

     {

         for( int i=n/2; i>1; i-- )

         {

             if( a[i]==0 && a[n-i]==0 )

             {

                     printf( "%d %d\n", i, n-i );

                 break;    

             }        

         }    

     }

     return 0;

 }

 

Problem F

  

  思路:由题意可知,一定有解,而且解空间很小, 故可以枚举;

  M=9983, n=A%M gcd( b,M )==1, ans=(A?B)%M,

  则 n == (ans*b)%M;

  因为: A%M == (A/B*B)%M==(A/B%M * B%M)%M== (ans*B%M)%M;

参考代码

View Code
View Code 

 #include <iostream> 

 #include <cstdio> 

 #include <string.h> 

 using namespace std; 

  

 int main(){ 

     int T; 

     scanf("%d",&T); 

     while(T--){ 

       __int64 n,b; 

       int x; 

       scanf("%I64d%I64d",&n,&b); 

       for(int i = 0;i < 9973; ++i){ 

           if(( b * i - n ) % 9973 == 0){ 

             x = i; 

             break; 

           } 

       } 

       printf("%d\n",x);  

     } 

     return 0; 

 }

 

 

你可能感兴趣的:(code)