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\n",index); 69 } 70 else printf("Bob\n"); 71 } 72 return 0; 73 }
这是改进后的代码,用线性筛法在打素数表的同时求出最小素因子····
初始化时每个数的最小素因子就是本身。
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\n",index); 59 } 60 else printf("Bob\n"); 61 } 62 return 0; 63 }