遲來的18.12.11的題解
18.12.11題解
素數個數(prime)
題目描述求{1,2,...,N} 中素數的個數。
輸入
1 個整數 N 。
輸出
1 個整數,表示素數的個數。
樣例輸入
10
樣例輸出
4
提示
對於 40% 的資料,1≤N≤106;
對於 80% 的資料,1≤N≤10 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;
}
2、1103: 數學尤拉函式(phi)
題目描述
對正整數n,n的尤拉函式(即φ(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)
3、1631: NOIP 2012 同餘方程(mod)
題目描述
求關於x的同餘方程ax ≡ 1 (mod b)的最小正整數解。
輸入
輸入只有一行,包含兩個正整數a, b,用一個空格隔開。
輸出
輸出只有一行,包含一個正整數x0,即最小正整數解。輸入資料保證一定有解。
樣例輸入
3 10
樣例輸出
7
提示
對於40%的資料,2 ≤b≤ 1,000;
對於60%的資料,2 ≤b≤ 50,000,000;
對於100%的資料,2 ≤a, b≤ 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的應用