BZOJ 3085: 反质数加强版SAPGAP
3085: 反质数加强版SAPGAP
Time Limit: 3 Sec Memory Limit: 256 MBSubmit: 496 Solved: 205
[Submit][Status][Discuss]
Description
先解释一下SAPGAP=Super AntiPrime, Greatest AntiPrime(真不是网络流),于是你就应该知道本题是一个关于反质数(Antiprime)的问题。下面给出反质数的定义:
将一个正整数i的约数个数记为g(i),如g(1)=1,g(2)=2,g(6)=4。
如果对于一个正整数k,对于任意正整数i<k,均有g(k)>g(i),则k被称为反质数。
比如说1,2,4,6,12就是前5个反质数。
现在给定一个N,求N以内最大的反质数。
你一定会认为这道题很简单,你曾经做过好多遍(它就是许许多多竞赛的原题呀),但是这次真的不一样。
Input
一个正整数N(1≤N≤10100)。
Output
一个正整数,表示不超过N的最大的反质数。
Sample Input
1000
Sample Output
840
HINT
HINT
对于5%的测试数据,n≤10000。
对于10%的测试数据,n≤100000。
对于20%的测试数据,n≤109。
对于35%的测试数据,n≤1017。
对于60%的测试数据,n≤1030。
对于100%的测试数据,n≤10100。
题解:这一题和BZOJ1053相似,只是数据加强了很多,所以不能像上一题那样暴力搜索了。需要加上剪纸优化,假设前m个质素为:p1,p2,p3.....pm,他们的指数为:q1,q2,q3.....qm;
窝萌假设K为最小的满足2^K>pi;
则2^(K-1)<pi;可以得到:2^q1*pi^qi>2^(q1+K-1)*pi^(qi-1)
如果要想qi为pi的指数,则必须满足:(q1+1)(qi+1)>(q1+K)qi;(如果不满足,则qi-1比qi更优)
则可以得到:qi<(q1+1)/(K-1);
以上对qi(i>=2)的限制;同理我们也可以对q1限制;
我们找一个不可能出现在质因子当中的质素pm;
设K为2^k>pm的最小整数;则得到不等式:2^q1>2(q1-k)*pm;
如果使得q1为2的指数,那么必有:q1>2(q1-k+1) -->q1<2k-1;
pm怎么取呢? q1q2q3....qm>N的最小的qm即可;
参考代码:
1 /************************************************************** 2 Problem: 3085 3 User: SongHL 4 Language: C++ 5 Result: Accepted 6 Time:2296 ms 7 Memory:1292 kb 8 ****************************************************************/ 9 10 #include<bits/stdc++.h> 11 using namespace std; 12 #define clr(a,b) memset(a,b,sizeof a) 13 typedef long long ll; 14 struct bignum{ 15 static const int mo=10000; 16 int a[27]; 17 bignum(){} 18 bignum(char *s){ 19 memset(a,0,sizeof(a)); 20 int l=strlen(s),cur=0,i; 21 for (i=l-1;i-3>=0;i-=4) 22 a[cur++]=(s[i-3]-48)*1000+(s[i-2]-48)*100+(s[i-1]-48)*10+s[i]-48; 23 for (int j=0;j<=i;j++) a[cur]=a[cur]*10+s[j]-48; 24 } 25 bignum(int x){ 26 memset(a,0,sizeof(a)); 27 a[0]=x; 28 } 29 inline void operator *= (int x){ 30 for (int i=0;i<27;i++) a[i]*=x; 31 for (int i=0;i<26;i++){ 32 a[i+1]+=a[i]/mo; 33 a[i]%=mo; 34 } 35 } 36 inline bool operator == (bignum x){ 37 for (int i=0;i<27;i++) 38 if (a[i]!=x.a[i]) return 0; 39 return 1; 40 } 41 inline bool operator < (bignum x){ 42 for (int i=26;i>=0;i--) 43 if (a[i]!=x.a[i]) return a[i]<x.a[i]; 44 return 0; 45 } 46 void print(){ 47 int cnt=26; 48 for (;!a[cnt]&&cnt;cnt--); 49 printf("%d",a[cnt]); 50 for (cnt--;cnt>=0;cnt--) printf("%04d",a[cnt]); 51 printf("\n"); 52 } 53 }n,ans,tmp; 54 char s[105]; 55 int pri[]={1, 2, 3, 5, 7, 11, 13, 17, 19, 23, 56 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 57 71, 73, 79, 83, 89, 97, 101,103,107,109, 58 113,127,131,137,139,149,151,157,163,167, 59 173,179,181,191,193,197,199,211,223,227, 60 229,233,239,241,251}; 61 int bin[]={ 62 1,2,2,3,3,4,4,5,5,5, 63 5,5,6,6,6,6,6,6,6,7, 64 7,7,7,7,7,7,7,7,7,7, 65 7,7,8,8,8,8,8,8,8,8, 66 8,8,8,8,8,8,8,8,8,8, 67 8,8,8,8,8}; 68 ll q1,m,mx; 69 void dfs(int k,bignum now,ll cnt,ll la) 70 { 71 if(cnt>mx||cnt==mx&&now<ans) ans=now,mx=cnt; 72 if(k!=1) la=min(la,q1/(bin[k]-1)); 73 ll tmp=cnt; 74 for(int i=1;i<=la;i++) 75 { 76 if(k==1) q1=i; 77 tmp+=cnt; 78 now*=pri[k]; 79 if(n<now) break; 80 dfs(k+1,now,tmp,i); 81 } 82 } 83 int main() 84 { 85 scanf("%s",s); 86 n=bignum(s); 87 tmp=bignum(1); 88 if (n==tmp) 89 { 90 printf("1"); 91 return 0; 92 } 93 for (;tmp<n||tmp==n;) tmp*=pri[++m]; 94 dfs(1,bignum(1),1,2*bin[m]-2); 95 ans.print(); 96 return 0; 97 } 98 99