题意:m个椰子,n个人,使得这n个人按次序醒来后能够将剩余的椰子分成n份多1,然后将1扔给猴子,自己拿走n份中的一份(这里的n一旦确定就不会改变),n次之后,剩余的椰子还能被n整除,求最大满足条件的n。
题解:考虑第一次m%n==1,所以对m-1分解质因数,即m-1的所有非1的约数都能在第一次分椰子的时候满足条件,然后枚举所有m-1的约数,最多2000多个,找出最大的。
View Code
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 const int mr=(1<<16)+1; 6 bool notp[mr]; 7 int pr[mr]; 8 int pn; 9 void getpri() 10 { 11 pn=0; 12 memset(notp,0,sizeof(notp)); 13 for(int i=2; i<mr; i++) 14 { 15 if(!notp[i]) 16 { 17 pr[pn++]=i; 18 } 19 for(int j=0; j<pn && i*pr[j]<mr; j++) 20 { 21 int k=i*pr[j]; 22 notp[k]=1; 23 if(i%pr[j]==0) 24 { 25 break; 26 } 27 } 28 } 29 } 30 int fac[100]; 31 int tot[100],top; 32 void div(int n) 33 { 34 for(int i=0;i<pn&&pr[i]*pr[i]<=n;i++) 35 { 36 if(n%pr[i]==0) 37 { 38 fac[top]=pr[i]; 39 tot[top]=0; 40 while(n%pr[i]==0) 41 { 42 tot[top]++; 43 n/=pr[i]; 44 } 45 top++; 46 } 47 } 48 if(n>1) 49 fac[top]=n,tot[top++]=1; 50 } 51 bool solve(int m,int n) 52 { 53 for(int i=0;i<n;i++) 54 { 55 if(m%n!=1) 56 return false; 57 m=(m-1)/n*(n-1); 58 } 59 return m%n==0; 60 } 61 int ans; 62 int po(int n,int k) 63 { 64 int p=1; 65 while(k--) 66 p*=n; 67 return p; 68 } 69 void dfs(int k,int res,int m) 70 { 71 if(k==top) 72 { 73 if(solve(m,res)) 74 ans=max(ans,res); 75 return; 76 } 77 for(int i=tot[k];i>=0;i--) 78 dfs(k+1,res*po(fac[k],i),m); 79 } 80 int main() 81 { 82 getpri(); 83 int m; 84 while(scanf("%d",&m),m>=0) 85 { 86 int mm=m-1; 87 top=0; 88 div(mm); 89 ans=-1; 90 dfs(0,1,m); 91 if(ans==-1) 92 printf("%d coconuts, no solution\n",m); 93 else 94 printf("%d coconuts, %d people and 1 monkey\n",m,ans); 95 } 96 return 0; 97 }