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\n",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\n",ans);
68     return 0;
69 }

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

我们枚举的

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

暴力简直可怕
时间: 2024-12-16 13:34:17

hihocoder 1165 : 益智游戏的相关文章

hihoCoder #1165 : 益智游戏 (挑战赛11 B题)

题意:在一个序列中找到两个数a和b,使得a*b的因子个数最多,输出最多的因子个数. 思路:数据较多,处理会很慢.对序列中每个数字进行质数分解求因子个数,然后按照因子个数降序排列,对前50个因子最多的数进行暴力求两两之积的因子个数就行了.1s左右就能出结果.低于50的就会WA了. 1 #include <bits/stdc++.h> 2 using namespace std; 3 int a[100005]; 4 pair<int,int> pa[100005]; 5 int ge

#1165 : 益智游戏

描述 幽香今天心情不错,正在和花田里的虫子玩一个益智游戏.这个游戏是这样的,对于一个数组A,幽香从A中选择一个数a,虫子从A中选择一个数b.a和b可以相同.她们的分数是a*b的因子的个数.幽香和虫子当然想要获得尽可能的高的分数,你能告诉她们应该选择哪两个数吗.由于幽香是个非常随意的人,数组A中的元素都是她随机选择的. 输入 一行一个数n,表示A中整数的数量.接下来一行n个数,分别表示a1,a2,...,an,为A中的元素. n <= 100000, 1 <= ai <= 100000保证

hihoCoder挑战赛11 益智游戏

题目链接:http://hihocoder.com/problemset/problem/1165 题面: 益智游戏 时间限制:20000ms 单点时限:1000ms 内存限制:256MB 描述 幽香今天心情不错,正在和花田里的虫子玩一个益智游戏. 这个游戏是这样的,对于一个数组A,幽香从A中选择一个数a,虫子从A中选择一个数b.a和b可以相同.她们的分数是a*b的因子的个数. 幽香和虫子当然想要获得尽可能的高的分数,你能告诉她们应该选择哪两个数吗. 由于幽香是个非常随意的人,数组A中的元素都是

hihocoder1165 益智游戏 (最多因子)

题目链接: http://hihocoder.com/problemset/problem/1165 题意: 从n个中选出两个数来使他们乘积的因子的个数最多. 分析: 对于一个数我们将其进行素因子分解 x= (p1^a1)*(p2^a2)*....*(pn^an); 那么x的因子数为(a1+1)*(a2+1)*...*(an+1); 然后我们可以预处理1到100000的因子的个数,然后 对输入的数据按照因子的个数排下序,然后枚举前200 个数的组合,求一下最大值就好了. 代码如下: #inclu

[hihoCoder#1381]Little Y&#39;s Tree

[hihoCoder#1381]Little Y's Tree 试题描述 小Y有一棵n个节点的树,每条边都有正的边权. 小J有q个询问,每次小J会删掉这个树中的k条边,这棵树被分成k+1个连通块.小J想知道每个连通块中最远点对距离的和. 这里的询问是互相独立的,即每次都是在小Y的原树上进行操作. 输入 第一行一个整数n,接下来n-1行每行三个整数u,v,w,其中第i行表示第i条边边权为wi,连接了ui,vi两点. 接下来一行一个整数q,表示有q组询问. 对于每组询问,第一行一个正整数k,接下来一

hihoCoder 1175:拓扑排序二

题目链接: http://hihocoder.com/problemset/problem/1175 题目难度:一星级(简单题) 今天闲来无事,决定刷一道水题.结果发现这道水题居然把我卡了将近一个钟头. 最后终于调通了.总结起来,原因只有一个:不够仔细. 思路不用细说了,就是拓扑排序的简单应用.然而,一些不起眼的细节才是让你掉坑里的真正原因. 猜猜哪儿可能出bug? // A simple problem, but you can't be too careful with it. #inclu

hihocoder [Offer收割]编程练习赛18 C 最美和弦(dp)

题目链接:http://hihocoder.com/problemset/problem/1532 题解:一道基础的dp,设dp[i][j][k][l]表示处理到第几个数,当前是哪个和弦错了几次初始x值是多少.这里还要再辅助一个val[k]表示处理到当前情况只错了k次的最小值是多少因为改变的不止是和弦还有初始值,可以看一下代码理解一下. #include <iostream> #include <cstring> #include <cstdio> #include &

1165: 零起点学算法72——首字母变大写

1165: 零起点学算法72--首字母变大写 Time Limit: 1 Sec  Memory Limit: 64 MB   64bit IO Format: %lldSubmitted: 705  Accepted: 439[Submit][Status][Web Board] Description 输入一个英文句子,将每个单词的第一个字母改成大写字母. Input 输入数据包含多个测试实例,每个测试实例是一个长度不超过100的英文句子,占一行. Output 请输出按照要求改写后的英文句

hihocoder #1190 : 连通性&#183;四 点双联通分量

http://hihocoder.com/problemset/problem/1190?sid=1051696 先抄袭一下 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 小Hi和小Ho从约翰家回到学校时,网络所的老师又找到了小Hi和小Ho. 老师告诉小Hi和小Ho:之前的分组出了点问题,当服务器(上次是连接)发生宕机的时候,在同一组的服务器有可能连接不上,所以他们希望重新进行一次分组.这一次老师希望对连接进行分组,并把一个组内的所有连接关联的服务器也视为这个组内