1. 程式人生 > >遲來的18.12.11的題解

遲來的18.12.11的題解

18.12.11題解

 

素數個數(prime)

題目描述求{1,2,...,N} 中素數的個數。

輸入

 1 個整數 N

 輸出

1 個整數,表示素數的個數。

 樣例輸入

10

樣例輸出

 4

提示

對於 40% 的資料,1N106

對於 80% 的資料,1N10 7

對於 100% 的資料,1 N <6*10 7

 

參考程式碼

#include <cassert>

#include <cstdio>

#include <cstring>

const int N = 100000000;

bool isPrime[N+1];   //陣列較大開在外面  用來記錄是否是素數

int primeCount, primes[5761455];

int main() {

   freopen("prime.in","r",stdin); 

   freopen("prime.out","w",stdout);

    int n; 

    assert(scanf("%d", &n) == 1);  //判斷輸入是否符合規定

    assert(1 <= n && n <= N);

    memset(isPrime, true, sizeof(isPrime));   //將初始定義為1(即假設他們都是素數)

    primeCount = 0;

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

{

        if (isPrime[i])

{

            primes[primeCount ++] = i;

        }

        for (int j = 0; j < primeCount && i * primes[j] <= n; ++ j)

 {

            isPrime[i * primes[j]] = false; //兩個數相乘後得到的數肯定不是素數標記

            if (i % primes[j] == 0)  //保證i>j 避免重複運算

{

                break;

            }

        }

    }

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

    return 0;

}

 

自己的程式碼

 

#include<cstdio>

#include<cstring>

using namespace std;

bool mark[6000000];

int main()

{

       int n,j,k=0,h;

       scanf("%d",&n);

       memset(mark,true,sizeof(mark));

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

       {

              for(j=2;i * j <= n && i>=j;j++)

              {

                     mark[i*j] = false;

                     }    

       }

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

              if( mark[i] == 1)

                     k++;

       printf("%d",k);

       return 0;

 }

 

 

 

 

 

 

 

 

 

 

 

 

 

 

21103: 數學尤拉函式(phi)

題目描述

對正整數nn的尤拉函式(即φ(N))是少於或等於n的數中與n互質的數的數目。例如φ(8)=4,因為1,3,5,7均和8互質。

輸入

一行一個整數N

輸出

一行一個整數φ(N)

樣例輸入

8

樣例輸出

4

提示

 

 

對於70%的資料,有N<=1000

 

對於100%的資料,有N<=231-1

 

參考程式碼

#include<iostream>

#include<cstring>

using namespace std;

long long n,ans;

int main()

{

    cin>>n;

    ans=n;

    int i=1;

    while(n!=1)

    {

        i++;

        if(n%i==0)

        {

            ans=ans/i*(i-1);

            n=n/i;

        }

        while(n%i==0) n=n/i;

    }

    cout<<ans;

    return 0;

}

 

 

自己的程式碼

#include<cstdio>

using namespace std;

long long n,m;

int main()

{

       scanf("%lld",&n);

       m=n;

       int i=1;

       while(n != 1)

       {

              i++;    //每迴圈一次就加1

              if(n % i == 0)   //可以被除的開的話

              {

                     m = m / i * (i-1); 

                     n /= i;

              }

              while(n%i==0) n=n/i;

       }       //這裡其實是一個遞迴

       printf("%lld",m);

       return 0;

}

 

公式:

就是這個公式

Euler(x)=x(1-1/p1)(1-1/p2)(1-1/p3)(1-1/p4)…..(1-1/pn)

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

31631: NOIP 2012 同餘方程(mod)

題目描述

求關於x的同餘方程ax ≡ 1 (mod b)的最小正整數解。

輸入

輸入只有一行,包含兩個正整數ab,用一個空格隔開。

輸出

輸出只有一行,包含一個正整數x0,即最小正整數解。輸入資料保證一定有解。

 

樣例輸入

3 10

樣例輸出

7

提示

對於40%的資料,2 ≤b≤ 1,000

 

對於60%的資料,2 ≤b≤ 50,000,000

 

對於100%的資料,2 ≤ab≤ 2,000,000,000

 

參考程式碼

#include<iostream>

using namespace std;

long long a,b,x,y;

void exgcd(long long a,long long b,long long &x,long long &y)

{

    if(b==0)

    {

        x=1;

        y=0;

        return;

    }

    exgcd(b,a%b,x,y);

    int z=x;

    x=y;

    y=z-y*(a/b);

}

int main()

{

  

    cin>>a>>b;

    exgcd(a,b,x,y);

    cout<<(x%b+b)%b<<endl;

}

 

自己的程式碼(也是學習來的)

#include<cstdio>

using namespace std;

long long a,b,x,y;

void exgcd(long long a,long long b,long long &x,long long &y)

{

    if(b==0)

    {

        x=1;

        y=0;

        return;

    }

    exgcd(b,a%b,x,y);

    int z=x;

    x=y;

    y=z-y*(a/b);

}

int main()

{

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

       exgcd(a,b,x,y);

       printf("%lld",(x%b+b)%b)

 }

 

是擴充套件gcd的應用