Zoj 3529 A Game Between Alice and Bob 数论+博弈Nim 快速求数中有多少个素数因子

本题涉及博弈论中的Nim游戏博弈。

Nim游戏博弈详解链接:

http://www.cnblogs.com/exponent/articles/2141477.html

本题解题报告详解链接:

http://blog.csdn.net/woshi250hua/article/details/7824609

我的代码,写的较挫,4000多ms,压着时间过,时间限制是5s.我预处理了所有1-5*10^6的数的素因子个数,用的是dp

的思想,先预处理1-5*10^6的数的最小素因子,存在a数组中,然后dp[i] = dp[i/a[i] ]+1;

我觉得我代码最挫的地方是在求最小素因子时费时太多。。。。

 1 #include <cstdio>
 2 #define N 5000005
 3 #define INF 0x7fffffff
 4 int p[N];//每个数有多少个素数因子
 5 int a[N];//每个数最小的素数因子
 6 int prime[700];//存素数表
 7 void init()
 8 {
 9     //打素数表,求出1-5005以内的素数和每个数的最小质因子
10     for(int i=0; i<700; ++i)
11         prime[i] = INF;
12     prime[0] = 2;
13     int num = 0;
14     for(int i=3; i<5005; ++i)
15     {
16         int x = 0;
17         while(i%prime[x] && prime[x] <= i)   ++x;
18         if( !(i%prime[x]) )
19             a[i] = prime[x];
20         else
21         {
22             prime[++num] = i;
23             a[i] = i;
24         }
25     }
26     a[2] =2;
27     for(int i=5005; i< N; ++i)
28     {
29         int x = 0;
30         while(i%prime[x] && prime[x] <= i)   ++x;
31         if( !(i%prime[x]) )
32             a[i] = prime[x];
33         else
34             a[i] = i;
35     }
36     p[2] = 1;
37     for(int i=3; i <N; ++i)
38         p[i] = p[i/a[i]] + 1;
39 }
40 int main()
41 {
42 //    freopen("in.cpp","r",stdin);
43     init();
44     int n;
45     int b[100005];
46     int t=0;
47     while(scanf("%d",&n) != EOF)
48     {
49         int ans ;
50         for(int i=0; i<n; ++i)
51         {
52             scanf("%d",&b[i]);
53             if(i)
54                 ans ^= p[b[i]];
55             else
56                 ans = p[b[i]];
57         }
58         printf("Test #%d: ",++t);
59         if(ans)
60         {
61             int index;
62             for(int i=0; i<n; ++i)
63                 if( (p[b[i]]^ans) < p[b[i]] )
64                 {
65                     index = i+1;
66                     break;
67                 }
68             printf("Alice %d
",index);
69         }
70         else printf("Bob
");
71     }
72     return 0;
73 }
View Code

 这是改进后的代码,用线性筛法在打素数表的同时求出最小素因子····

初始化时每个数的最小素因子就是本身。

 1 #include <cstdio>
 2 #define N 5000005
 3 #define INF 0x7fffffff
 4 int p[N];//每个数有多少个素数因子
 5 bool v[N]; //是否为素数
 6 int a[N];//每个数最小的素数因子
 7 int prime[N/10];//素数表
 8 //用打素数表的筛法求每个数的最小质因子
 9 void init()
10 {
11     for(int i=2; i<N; ++i)
12         a[i] = i;
13     int num=-1;
14     for(int i=2; i<N; ++i)
15     {
16         if(!v[i]) prime[++num] = i;
17         for(int j=0; j<=num && i*prime[j] < N; ++j)
18         {
19             int t = i*prime[j];
20             v[t] =1;
21             if(a[t] > prime[j]) a[t] = prime[j];
22             if(i%prime[j] == 0) break;
23         }
24     }
25     p[2] = 1;
26     for(int i=3; i <N; ++i)
27         p[i] = p[i/a[i]] + 1;
28 }
29 
30 int main()
31 {
32 //    freopen("in.cpp","r",stdin);
33     init();
34     int n;
35     int b[100005];
36     int t=0;
37     while(scanf("%d",&n) != EOF)
38     {
39         int ans ;
40         for(int i=0; i<n; ++i)
41         {
42             scanf("%d",&b[i]);
43             if(i)
44                 ans ^= p[b[i]];
45             else
46                 ans = p[b[i]];
47         }
48         printf("Test #%d: ",++t);
49         if(ans)
50         {
51             int index;
52             for(int i=0; i<n; ++i)
53                 if( (p[b[i]]^ans) < p[b[i]] )
54                 {
55                     index = i+1;
56                     break;
57                 }
58             printf("Alice %d
",index);
59         }
60         else printf("Bob
");
61     }
62     return 0;
63 }
View Code
原文地址:https://www.cnblogs.com/allh123/p/3234290.html