输入输出样例
输入 #1复制
10 5 14 9
93 45 84 59
145 95 143 92
995 487 996 488
2000 1000 1999 999
9998 4999 9996 4998
输出 #1复制
0.12587
505606.46055
1.28223
0.48996
2.00000
3.99960
// 唯一分解定理 任意一个数都可以写成好多个素数想乘的形式
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<vector>
using namespace std;
const int Maxn = 10000;
int e[Maxn + 1];
vector<int> primes;
inline bool is_prime(int n) {
int m = sqrt(n + 0.5);
for(int i=2; i<=m; i++)
if(n % i == 0) return false;// 暴力检验素数
return true;
}
inline void Add(int n,int d) {
for(int i=0; i<primes.size(); i++){
while(n % primes[i] == 0) {
n /= primes[i];
e[i] += d;
}
if(n == 1) break;
}
return ;
}
inline void add(int n,int d) {
for(int i=1; i<=n; i++)
Add(i,d);
}
bool vis[Maxn + 1];
int main(int argc,char* argv[]) {
memset(vis,0,sizeof(vis));
vis[0] = vis[1] = 1;// 1 代表不是素数
for(int i=2; i<=Maxn; i++) {// 欧拉筛法 就当复习一下了
if(!vis[i]) primes.push_back(i);
for(int j=0; j<primes.size()&&i*primes[j]<=Maxn; j++) {
vis[i * primes[j]] = 1;
if(i % primes[j] == 0) break;
}
}
//for(int i=0; i<primes.size(); i++) printf("%d ",primes[i]);
int p,q,r,s;
while(scanf("%d%d%d%d",&p,&q,&r,&s) == 4) {
memset(e,0,sizeof(e));
add(p,1);
add(p-q,-1);
add(q,-1);
add(r,-1);
add(s,1);
add(r-s,1);
double Ans = 1;
for(int i=0; i<primes.size(); i++)
if(e[i]) Ans *= pow(primes[i],e[i]);
printf("%.5lf\n",Ans);
}
return 0;
}
// 埃氏筛法
int visit[maxn];
void Prime(){
mem(visit,0); //初始化都是素数
visit[0] = visit[1] = 1; //0 和 1不是素数
for (int i = 2; i <= maxn; i++) {
if (!visit[i]) { //如果i是素数,让i的所有倍数都不是素数
for (int j = i*i; j <= maxn; j += i) {
visit[j] = 1;
}
}
}
- 埃氏筛法的缺陷 :对于一个合数,有可能被筛多次。例如 30 = 2 * 15 = 3 * 10 = 5*6……那么如何确保每个合数只被筛选一次呢?我们只要用它的最小质因子来筛选即可,这便是欧拉筛法。
// 欧拉筛法
for(int i=2; i<=Maxn; i++) {// 欧拉筛法 就当复习一下了
if(!vis[i]) primes.push_back(i);
for(int j=0; j<primes.size()&&i*primes[j]<=Maxn; j++) {
vis[i * primes[j]] = 1;
if(i % primes[j] == 0) break;
}
}
- 关于 i%prime[j] == 0 就break的解释 :(其实这玩意我这个寒假回来看,第一遍自己啥也没看懂,还是去网上找的,看了老半天勉强算是看懂了吧)当 i是prime[j]的倍数时,i = kprime[j],如果继续运算 j+1,i * prime[j+1] = prime[j] * k prime[j+1],这里prime[j]是最小的素因子,当i = k * prime[j+1]时会重复,所以才跳出循环。
举个例子 :i = 8 ,j = 1,prime[j] = 2,如果不跳出循环,prime[j+1] = 3,8 * 3 = 2 * 4 * 3 = 2 * 12,在i = 12时会计算。因为欧拉筛法的原理便是通过最小素因子来消除。