• hihocoder 1165 : 益智游戏


    时间限制:20000ms
    单点时限:1000ms
    内存限制:256MB

    描述

    幽香今天心情不错,正在和花田里的虫子玩一个益智游戏。
    这个游戏是这样的,对于一个数组A,幽香从A中选择一个数a,虫子从A中选择一个数b。a和b可以相同。她们的分数是a*b的因子的个数。
    幽香和虫子当然想要获得尽可能的高的分数,你能告诉她们应该选择哪两个数吗。
    由于幽香是个非常随意的人,数组A中的元素都是她随机选择的。

    输入

    一行一个数n,表示A中整数的数量。
    接下来一行n个数,分别表示a1,a2,...,an,为A中的元素。

    n <= 100000, 1 <= ai <= 100000
    保证所有的ai都是随机生成的。

    输出

    一行表示最大的分数。

    怎么想都没有啥算法,其实正确的暴力姿势也能出奇迹。

    刚开始只想到我们求得每个数的因子个数b[i],对然后巧用break;能混过去;

    这种形式:if (ans>b[i]*b[j]) break 一层循环,b数组是按照 因子个数从大到小 排序,所以正确。

    但是 我们每次算(a[i],a[j])的因子个数总和时还要 一步一步枚举过去,TLE。

    比如这段代码:

    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    #include<string.h>
    #include<string>
    
    using namespace std;
    
    #define N 100001
    
    int p[N];
    int b[N],t;
    
    struct node
    {
        int x,y;
    }a[N];
    void prime()
    {
        for (int i=2;i<N;i++)
        if (!b[i])
        for (int j=i+i;j<N;j+=i)
        b[j]=1;
    
        for (int i=2;i<N;i++)
        if (!b[i]) p[++t]=i;
    }
    
    int work(int x,int y)
    {
       int sum=1;
       int t=1;
       while (1)
       {
           if (x==1&&y==1) return sum;
           int v=1;
           if (x%p[t]==0)
           {
               while (x%p[t]==0)
               {
                   v++;
                   x/=p[t];
               }
           }
           if (y%p[t]==0)
           {
               while (y%p[t]==0)
               {
                   v++;
                   y/=p[t];
               }
           }
           t++;
           sum*=v;
       }
    }
    
    int cmp(node  a,node  b)
    {
        return a.y>b.y;
    }
    
    int main()
    {
        prime();
    
        memset(b,0,sizeof(b));
        int n;
        scanf("%d",&n);
        for (int i=1;i<=n;i++)
        scanf("%d",&a[i].x),a[i].y=work(a[i].x,1);
        //for (int i=1;i<=n;i++) printf("%d ",a[i].y);
        sort(a+1,a+n+1,cmp);
        int ans=0;
        for (int i=1;i<=n;i++)
        for (int j=i+1;j<=n;j++){
        if (ans>a[i].y*a[j].y) break;
        else ans=work(a[i].x,a[j].x);
        }
    
        printf("%d
    ",ans);
        return 0;
    }
    

      于是看到一个模板:线性帅法,并且每次能求出一个数的前驱素数因子

     1 #include<cstdio>
     2 #include<algorithm>
     3 #include<cmath>
     4 #include<string.h>
     5 #include<string>
     6 
     7 using namespace std;
     8 
     9 #define N 100001
    10 
    11 int p[N];
    12 int b[N],t=0;
    13 
    14 struct node
    15 {
    16     int x,y;
    17 }a[N];
    18 void prime()
    19 {
    20    for (int i=2;i<N;i++)
    21    {
    22        if (!b[i]) p[++t]=b[i]=i;
    23        for (int j=1;j<=t&&p[j]<=b[i]&&p[j]<=N/i;++j) b[i*p[j]]=p[j];
    24    }
    25    b[1]=N;
    26 }
    27 
    28  int work(int x,int y)
    29 {
    30    int sum=1;
    31    int c=0;
    32    while (x>1||y>1)
    33    {
    34        if (b[x]<b[y]) c=b[x];
    35        else c=b[y];
    36        int v=1;
    37        for (;b[x]==c;x/=c) v++;
    38        for (;b[y]==c;y/=c) v++;
    39        sum*=v;
    40    }
    41    return sum;
    42 }
    43 inline int cmp(node  a,node  b)
    44 {
    45     return a.y>b.y;
    46 }
    47 
    48 int main()
    49 {
    50     prime();
    51 
    52     int n;
    53     scanf("%d",&n);
    54     for (int i=1;i<=n;i++)
    55     scanf("%d",&a[i].x),a[i].y=work(a[i].x,1);
    56 
    57     sort(a+1,a+n+1,cmp);
    58     int ans=a[1].y;
    59     n=min(n,200);
    60 
    61     for (int i=1;i<=n;i++)
    62     for (int j=i+1;j<=n;j++){
    63     if (ans>a[i].y*a[j].y) break;
    64     else ans=max(ans,work(a[i].x,a[j].x));
    65     }
    66 
    67     printf("%d
    ",ans);
    68     return 0;
    69 }
    View Code

    但是你 会发现还是很慢,超级慢,9000ms 了,然后又看一份代码,发现!!

    我们枚举的

     for (int i=1;i<=n;i++)
        for (int j=i+1;j<=n;j++)
    因为 n可能很大,大概10万,但是后面大多没用,所以我们只要 n<=1000,之类的就够了。

    暴力简直可怕

  • 相关阅读:
    [React Router v4] Render Catch-All Routes with the Switch Component
    [React Router v4] Render Nested Routes
    关系数据库规范化理论 函数依赖与范式理论
    Notepad++背景颜色设置
    initial pointer [expert c]
    世界微波射频领域传奇人物
    hdu 4619 Warm up 2 ( 二分图最大匹配 )
    关于数据的归档存入文件和读取文件
    android中通过自定义xml实现你需要的shape效果 xml属性配置
    Java和C#中String直接赋值与使用new创建(==与equals进行比较)的区别
  • 原文地址:https://www.cnblogs.com/forgot93/p/4476610.html
Copyright © 2020-2023  润新知