2015-06-11 16:39:12
【传送门】
A题、B题签到。
C题:欧拉筛法
题意:给出 n 个数,它们的积为分子;再给出 m 个数,它们的积为分母。将这个分数约分之后输出,格式与输入一样。
思路:一开始的思路是对每个数 sqrt(n) 质因数分解,然后分别记录分子/分母质因子的数量,然后约分,但是TLE。
后来才知道,可以用欧拉筛法来线性处理出每个数的最小素因子(线性复杂度基于的是每个数只被最小素因子筛掉,所以每个数只被筛一次)
处理出每个数的最小素因子这个表后,对于分子的n个数和分母的m个数进行分解,记录下质因数的数量。然后
再对每个数分解一次,把能约分的质因数约掉即可。
#include <cstdio> #include <cstring> #include <cstdlib> #include <cmath> #include <vector> #include <map> #include <set> #include <stack> #include <queue> #include <string> #include <iostream> #include <algorithm> using namespace std; #define getmid(l,r) ((l) + ((r) - (l)) / 2) #define MP(a,b) mkake_pair(a,b) #define PB(a) push_back(a) typedef long long ll; typedef pair<int,int> pii; const double eps = 1e-8; const int INF = (1 << 30) - 1; const int MAXN = 10000010; int n,m,A,B; int tA[1000010],tB[1000010]; int c[MAXN],p[MAXN]; map<int,int> mp1,mp2; int f1[MAXN],f2[MAXN]; void Init(){ int cnt = 0; for(int i = 2; i < MAXN; ++i){ if(!c[i]) c[i] = p[cnt++] = i; for(int j = 0; j < cnt && i * p[j] < MAXN; ++j){ c[i * p[j]] = p[j]; if(i % p[j] == 0) break; } } } int main(){ Init(); scanf("%d%d",&n,&m); for(int i = 1; i <= n; ++i){ scanf("%d",&A); tA[i] = A; while(A > 1){ f1[c[A]]++; A /= c[A]; } } for(int i = 1; i <= m; ++i){ scanf("%d",&B); tB[i] = B; while(B > 1){ f2[c[B]]++; B /= c[B]; } } printf("%d %d\n",n,m); for(int i = 1; i <= n; ++i){ int res = tA[i]; while(tA[i] > 1){ if(f2[c[tA[i]]]){ f2[c[tA[i]]]--; res /= c[tA[i]]; } tA[i] /= c[tA[i]]; } printf("%d ",res); } puts(""); for(int i = 1; i <= m; ++i){ int res = tB[i]; while(tB[i] > 1){ if(f1[c[tB[i]]]){ f1[c[tB[i]]]--; res /= c[tB[i]]; } tB[i] /= c[tB[i]]; } printf("%d ",res); } puts(""); return 0; }