codeoforces 932A
题意:
A和B在玩一个游戏,首先有一个X0 >= 3,之后选择一个小于X0的质数p,然后在找一个最小的X1 >= X0,并且p可以整除X1;之后再选择一个小于X1的质数p,然后再找一个最小的X2 >= X1,并且p可以整除X2。。。。
总之,每次会选择一个p小于Xi-1,然后找一个最小的Xi >= Xi-1,使得p可以整除Xi。注意如果p已经整除Xi-1,那么之后的数字就不会变了。
现在给出X2,要找出最小的X0,A和B玩游戏的时候并不play optimally。保证X2是一个合数。
思路:
如果已知一个数Xi,那么首先找到这个数的因子中最大的质数p,那么Xi-1的范围就是Xi – p + 1 ~ Xi(本身是可以取的),不可能从其它数字当中取得。
举个比较直观的例子,假设X2为28,最大的素数因子是7,假设X1取21,那么X2也只能取21,但是X1从22 ~ 28的范围,X2的取值都是28。
根据这个方法,就可以从X2推X1的范围,再从X1推X0。
复杂度是O(Nsqrt(N))。j * j <= n 这个式子是个好东西。
代码:
1 #include <stdio.h> 2 #include <string.h> 3 #include <algorithm> 4 #include <vector> 5 using namespace std; 6 7 const int N = 1e6 + 5; 8 9 bool prime[N]; 10 11 vector<int> v; 12 vector<int> p; 13 14 int main() 15 { 16 for (int i = 2;i <= 1000000;i++) 17 { 18 if (!prime[i]) 19 { 20 p.push_back(i); 21 for (int j = i * 2;j <= 1000000;j += i) 22 { 23 prime[j] = 1; 24 } 25 } 26 } 27 28 int n; 29 30 scanf("%d",&n); 31 32 int d; 33 34 for (int i = 2;i <= n;i++) 35 { 36 if (!prime[i] && n % i == 0) 37 { 38 d = i; 39 } 40 } 41 42 for (int i = n - d + 1;i <= n;i++) 43 { 44 if (prime[i]) 45 { 46 v.push_back(i); 47 //printf("%d ",i); 48 } 49 } 50 51 int ans = 1e7; 52 53 for (int i = 0;i < v.size();i++) 54 { 55 int x = v[i]; 56 57 int tmp = 0; 58 59 for (int j = 2;j * j <= x;j++) 60 { 61 if (x % j == 0) 62 { 63 if (!prime[j]) tmp = max(tmp,j); 64 if (!prime[x / j]) tmp = max(tmp,x/j); 65 } 66 } 67 68 ans = min(ans,x - tmp + 1); 69 } 70 71 printf("%d\n",ans); 72 73 return 0; 74 }
康复训练中~欢迎交流!