UVA 11752 The Super Powers —— 数学与幂

题目链接:https://vjudge.net/problem/UVA-11752



题解:

1.首先变量必须用unsig long long定义。

2.可以分析得到,当指数为合数的时候,该值合法。

3.由于最大值为(2^64)-1,而最小的合数为4, 所以底数最大都不超过(2^16)。且指数最大不超过64。

那么就可以:

枚举底数,然后计算出在最大值范围内,可以取到的最大指数。当最大指数小于4时,可以退出循环了。

然后枚举指数,从4开始,当指数为合数时,该值合法。

4.时间复杂度:O((2^16)* 64) < O(1e7)



反思:
现场做的时候,发现了:底数为素数,指数为合数的组合是合法的,且不会出现重复。

也知道底数在1e5之内,但却没有发现指数最大都不超过64(原因没有以 2^64 为分析对象)。

当时的想法是:在1e5之内筛选出素数和合数,然后素数与合数组合。但是没想到怎么刹车以防超过最大值。

原来是:在组合之前,先计算出该素数下最大的指数,然后就以这个最大指数为刹车基准。

只恨当时没想到……

而且:不管底数是否为素数,直接枚举也不会超时。所以才导致想到了复杂的方法,这源于没有事先对复杂度作出准确的估计。




代码如下:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <string>
#include <set>
#define ms(a,b) memset((a),(b),sizeof((a)))
using namespace std;
typedef long long LL;
const int INF = 2e9;
const LL LNF = 9e18;
const int mod = 1e9+7;
const int maxn = 1e5+100;

int vis[100], p[100], cnt = 0;
typedef unsigned long long ull;
void init()
{
    int m = (64+0.5);
    for(int i = 2; i<=m; i++)
    if(!vis[i])
    {
        p[++cnt] = i;
        for(int j = i*i; j<64; j += i)
            vis[j] = 1;
    }
}

set<ull>s;  //用set完成了排序加去重的功能

int main()
{
    init(); //标记在64以内的合数
    ull  maxx = (1LL<<64)-1;    //最大值
    for(ull i = 2;; i++)    //枚举底数
    {
        ull x = maxx;
        int t = 0;
        //尽量不要用取对数的方法求得t,因为常常出现浮点数的相关问题
        while(x>=i) //计算i的最大次幂
        {
            t++;
            x /= i;
        }
        if(t<4) break;
        x = 1;
        for(int j = 1; j<=t; j++)
        {
            x *= i;
            if(vis[j])
                s.insert(x);
        }
    }

    s.insert(1);
    set<ull>::iterator it;
    for(it = s.begin(); it!=s.end(); it++)
        cout<<*it<<endl;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值