1. 程式人生 > >杭電 ACM Step Chapter Two Section 1

杭電 ACM Step Chapter Two Section 1

最小公倍數

這裡寫圖片描述

  • 兩個數的最小公倍數=兩個數的乘積/兩個數的最大公約數,即[a,b]=a*b/(a,b)。問題轉化成求最大公約數,這裡使用歐幾里得輾轉相除法求解。
#include <stdio.h>
#include <stdlib.h>
int gcd(int a,int b)//求兩個正整數的最大公約數
{
    int r,t;
    if(a<b) //保證a>b
    {
        t=a;
        a=b;
        b=t;
    }
    while(a%b !=0)
    {
        r=a%b
; a=b; b=r; } return b; } int main() { int a,b; int lcm,g; while(scanf("%d%d",&a,&b)!=EOF) { g=gcd(a,b); lcm=(a*b)/g; printf("%d\n",lcm); } return 0; }

How many prime numbers

這裡寫圖片描述

#include <stdio.h>
#include <stdlib.h>
#include <math.h> int IsPrime(int a) { if(a<2) return 0;//小於2的數既不是素數也不是合數 for(int i=2;i<=sqrt(a);i++) { if(a%i==0) return -1;//能夠整除非1的某個數,說明是合數 } return 1;//判斷為素數,返回1 } int main() { int N;/*將輸入資料的個數*/ int a,sum; while(scanf("%d",&N)!=EOF) { sum=0
; while(N--) { scanf("%d",&a); if(IsPrime(a)==1) sum++; } printf("%d\n",sum); } return 0; }

相遇週期

這裡寫圖片描述

  • 這道題中的相遇週期即兩個衛星各自週期的最小公倍數。所以問題轉化為求分數的最小公倍數問題。
  • 解法:首先將分數化為最簡形式,然後求分子的最小公倍數作為分子,分母的最大公約數作為分母
  • 注意點:資料型別有問題,剛開始寫好程式碼卻報錯,上網借鑑別人的程式碼,發現數據型別不是簡單的int型,輸入中給出的那一串\\\符號已經表明數字會很大,所以需要使用更長的資料型別。
#include <stdio.h>
__int64 _gcd(__int64  x,__int64  y)
{
    __int64  r;
    if(x<y)
    {
        __int64  temp=y;
        y=x;
        x=temp;
    }
    while(x%y !=0)
    {
        r=x%y;
        x=y;
        y=r;
    }
    return y;
}
__int64  main()
{
    __int64  T;
    __int64  a,b,c,d;
    scanf("%I64d",&T);
    __int64  m,n;
    while(T--)
    {
        scanf("%I64d/%I64d%I64d/%I64d",&a,&b,&c,&d);
        /*首先將分數化為最簡形式*/
        m=_gcd(a,b);
        a=a/m;
        b=b/m;
        n=_gcd(c,d);
        c=c/n;
        d=d/n;

        m=_gcd(b,d);//對分母求最大公約數
        n=_gcd(a,c);
        n=(a*c)/n;//對分子求最小公倍數
        if(n%m==0) printf("%I64d\n",n/m);
        else printf("%I64d/%I64d\n",n,m);
    }
    return 0;
}

Largest prime factor

這裡寫圖片描述

  • 初始的思路是將範圍內所有的素數找出並儲存到陣列A中,然後對輸入的資料在A中尋找其最大素因子,其下標即所在位置,但是提交發現超時
  • 後來借鑑網上思路,利用素數篩選法的思路解決問題
#include <stdio.h>
#include <math.h>
#define max 1000001
int LPF[max];/*注意非靜態變數陣列不能開的太大*/
int main()
{
    for(int i=0;i<max;i++) LPF[i]=0;
    int n,postion=0;//positon表示某個素數在素數表中的位置
    LPF[1]=0;
    for(int i=2;i<max;i++)
    {
        if(LPF[i]==0) //如果i還未被小於自身的任何素數整除,則確定i也是素數
        {
            postion++;
            for(int j=i;j<max;j=j+i) LPF[j]=postion;
            //所有是i的倍數的整數,LPF的值暫時為positon,不管更新,即得到最大素因子的位置
        }
    }
    while(scanf("%d",&n) != EOF)
    {
        printf("%d\n", LPF[n]);
    }
    return 0;
}

又見GCD

這裡寫圖片描述

#include <stdio.h>
int _gcd(int x,int y)
{
    if(x<y)
    {
        int temp=y;
        y=x;
        x=temp;
    }
    int r=y;
    while(x%y)
    {
        r=x%y;
        x=y;
        y=r;
    }
    return r;
}
int main()
{
    int n;
    int a,b,c;
    scanf("%d",&n);
    int max=10;
    for(int i=2;i<7;i++) max=max*10;
    while(n--)
    {
        scanf("%d%d",&a,&b);
        c=2*b;
        for(int i=3;c<max;i++)
        {
            if(_gcd(a,c)==b)
            {
                printf("%d\n",c);
                break;
            }
            c=i*b;
        }
    }
    return 0;
}

七夕節

這裡寫圖片描述
這裡寫圖片描述

#include <stdio.h>
int main()
{
    int A[500005];
    A[1]=0;
    for(int i=2;i<500001;i++) A[i]=1;//大於1的數都有因子1
    for(int i=2;i<500001;i++) 
    {
        for(int j=2*i;j<500001;)
        {
            A[j]=A[j]+i;//記錄數j的因子和
            j=j+i;
        }
    }
    int T,N;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d",&N);
        printf("%d\n",A[N]);
    }
    return 0;
}

找新朋友

這裡寫圖片描述

  • 尤拉函式:對於正整數n,尤拉函式就是小於或者等於n的數中與n互質的數的數目
  • 通過百度可以得到尤拉函式的通式。根據通式編寫程式碼。
#include <stdio.h>
#define max 32768
int A[max];
void eular()
{
    A[1]=1;
    for(int i=2;i<max;i++) A[i]=i;
    for(int i=2;i<max;i++)
    {
        if(A[i]==i)
        {
            for(int j=i;j<max;j=j+i)
                A[j]=A[j]/i*(i-1);//尤拉通式
        }
    }
}
int main()
{
    int CN,N;
    eular();
    scanf("%d",&CN);
    while(CN--)
    {
        scanf("%d",&N);
        printf("%d\n",A[N]);
    }
    return 0;
}