Euler Project 29

Distinct powers
Problem 29
Consider all integer combinations of ab for 2 ≤ a ≤ 5 and 2 ≤ b ≤ 5:

22=4, 23=8, 24=16, 25=32
32=9, 33=27, 34=81, 35=243
42=16, 43=64, 44=256, 45=1024
52=25, 53=125, 54=625, 55=3125
If they are then placed in numerical order, with any repeats removed, we get the following sequence of 15 distinct terms:

4, 8, 9, 16, 25, 27, 32, 64, 81, 125, 243, 256, 625, 1024, 3125

How many distinct terms are in the sequence generated by ab for 2 ≤ a ≤ 100 and 2 ≤ b ≤ 100?

Answer:
9183
Completed on Tue, 4 Jul 2017, 15:11

本来自己Python大数+set水过,然后看到网上的神python代码,人生苦短,快用Python啊··:

import itertools  #
print len(set(a**b for a,b in itertools.product(xrange(2,11), repeat=2)))

接下来C的思路,时间O(nlogn),空间O(n):
听了二璇妹妹一番话决定要好好写博客了,,,,,所以注释详细点,,,
思路:只考虑那些最小底数他们会产生哪些幂次,比如2,首先2本身会有2^2~2^100(99个),然后4(其实我们把他看成2^2次方),那么会新增哪些2的幂次呢?显然(2,4,6·······200)新增的有50个,接下来又考虑2^3,2^4,,,2^log2(100)这些数。
接下来我们发现3,9,27,其实规律是一样的,3本身也是3^2~3^100(99个),然后9,又会新增50个,所以我先给打个表,,,具体看代码吧。

#include<bits/stdc++.h>
using namespace std;

#define MAXN 100

bool vis[MAXN+10];   //标记数组,是否已经访问过
int cnt[MAXN+10];    //计数,最小底数的k次方可以增加多少个新的数
void Init_cnt()      //预处理一下cnt数组
{
    set<int> st;                 //一个集合,里面是最小底数可能出现的幂
    for(int i=2;i<=MAXN;i++)     //先将最小底数一次幂都放集合里
        st.insert(i);
    cnt[1]=st.size();            //比如我们只考虑2这个最小底数可能出现的幂,那么2本身就有2^2~2^100,
    for(int i=2;powl(2,i)<=MAXN;i++)       //接下来对于(2^2),(2^3)....(2^log2(MAXN))又会重复幂运算,但是都可以把他们看成最小底数的新的幂次,而且对于不同的最小底数都是一样的
    {
        int last_st=st.size();
        for(int j=i+i,t=1;t<MAXN;t++,j+=i) //对于当前这个由最小底数产生的数,比如2,会得到4,8,16,,,统计他们实际上是2的多少次幂
        {
            st.insert(j);
        }
        cnt[i]=st.size()-last_st;  //假如最小底数的i次方小于MAXN(本题中100)那么就加上cnt[i]
    }
}
int main()
{
    Init_cnt();
    memset(vis,0,sizeof(vis)); //初始化一下标记数组
    int ans=0;
    for(int i=2;i<=MAXN;i++)
    {
        if(vis[i]) continue; //如果已经被标记了,跳过
        ans+=cnt[1];         //对于当前没有continue的i,他就是最小底数,那么统计他可能出现的幂次比如2,首先本身2^2~2^100(99)要加上
        for(int j=2;powl(i,j)<=MAXN;j++)  //然后2^2,2^3,,在之前init()中已经统计好了,只要2^j是小于100的就加上
        {
                ans+=cnt[j];
                vis[(int)powl(i,j)]=1;
        }
    }
    cout<<ans<<endl;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值