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
",ans);
72     
73     return 0;
74 }
原文地址:https://www.cnblogs.com/kickit/p/8809580.html