LOJ 1289 求出前n个数的最小公倍数
n<=10^8, 答案要模2^32.
思路: 这道题开始想了很多东西都不行。 后来突然想到了方法。
手下我打出10^8的素数表。 如果用一般的方法肯定是不行的。 这里我用区间素数求法。将10^8分成100段。 这样的话就可以打出素数表。
打出素数表之后,我在求出前i项的最小公倍数。同样数组还是开不够。这样的话我还是将10^8分成1000000段,
f【1】表示前100个数的最小公倍数,f【2】是前200个。。。。。
最后给出一个n,先求出f[n/100],在对剩下的部分处理就行。
AC代码:
View Code
1 #include <iostream> 2 #include <cstdio> 3 #include <string> 4 #include <cstring> 5 #include <queue> 6 #include <cmath> 7 #include <algorithm> 8 using namespace std; 9 typedef unsigned long long ULL; 10 11 const int N = 6010000; 12 const ULL P = 1ULL<<32, M = 100000000; 13 int p[N], num; 14 ULL f[1010000], n; 15 bool np[N] = {0}; 16 void getprime(int L, int U) 17 { 18 memset(np, 0, sizeof(np)); 19 int su = sqrt((double)U), d=U-L+1; 20 for(int i=L%2; i<d; i+=2) 21 np[i] = 1; 22 for(int i=3; i<=su; i+=2) 23 { 24 int j = L/i*i; 25 if(j<L) j+=i; 26 if(j == i) j+=i; 27 j = j-L; 28 for(; j<d;j+=i) 29 np[j] = 1; 30 } 31 if(L <= 1) np[1-L] = 1; 32 if(L <= 2) np[2-L] = 0; 33 for(int i=0; i<d; i++) 34 if(!np[i]) 35 p[num++] = i+L; 36 } 37 38 void getp() 39 { 40 for(int i=0; i<100; i++) 41 { 42 getprime(i*1000000+1, (i+1)*1000000); 43 } 44 for(int i=0;i <= 1000000; i++) 45 f[i] = 1; 46 ULL now; 47 for(int i=0; i<num; i++) 48 { 49 now = p[i]; 50 while(now <= M) 51 { 52 f[now/100+1] *= p[i]; 53 now *= p[i]; 54 } 55 } 56 for(int i=1; i<=1000000; i++) 57 { 58 f[i] *= f[i-1]; 59 if(f[i]>= P) f[i] %= P; 60 } 61 } 62 63 ULL get(ULL n) 64 { 65 for(int i=0; i<num &&((ULL)p[i])*p[i] <= n; i++) 66 { 67 if(n % p[i] == 0) 68 { 69 while(n%p[i] == 0) 70 n /= p[i]; 71 if(n == 1) return p[i]; 72 return 1; 73 } 74 } 75 return n; 76 } 77 78 void solve() 79 { 80 ULL ans = f[n/100]%P; 81 for(ULL i=max(n/100*100,1ULL); i<=n; i++) 82 { 83 ans *= get(i); 84 if(ans >= P) ans %= P; 85 } 86 printf("%llu\n", ans); 87 } 88 89 int main() 90 { 91 getp(); 92 int t; 93 scanf("%d", &t); 94 for(int i=1; i<=t; i++) 95 { 96 scanf("%llu", &n); 97 printf("Case %d: ",i); 98 solve(); 99 } 100 return 0; 101 }


浙公网安备 33010602011771号