• BZOJ 3085: 反质数加强版SAPGAP


    3085: 反质数加强版SAPGAP

    Time Limit: 3 Sec  Memory Limit: 256 MB
    Submit: 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("
    ");
    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   
    View Code
  • 相关阅读:
    彻底屏蔽淘宝网、易趣
    日期处理string 与 DateTime相互转化
    手机进水!!!!!!!!!
    解决VS.net "Automation 服务器不能创建对象"
    综艺大哥大
    计算当前日期是任意时间段内第几周的函数
    吉祥三宝>馒头无极版
    如何在ASP.NET中使用JavaScript脚本
    IDEA工具开发一些辅助功能设置
    Linux命令行模式下挂载U盘与光驱
  • 原文地址:https://www.cnblogs.com/csushl/p/9884089.html
Copyright © 2020-2023  润新知