UVA136 求第1500个丑数

枚举大范围数据。。暴力检查题目条件

#include <iostream>
#include <cstdio>
#include <vector>
#include <algorithm>
#include <map>
using namespace std;
vector<int> Prime;
typedef long long ll;
bool isPrime(ll x){
    ll i;
    if(x==1) return false;
    for(i=2;i*i<=x;++i){
        if(x%i==0) return false;
    }
    return true;
}
vector<int> Set;
map<int,int> mp;
int pri[]={2,3,5,6,15,10,30};
bool jud(ll x){
    ll temp=x;
        while(temp!=0&&temp%2==0){
            temp/=2;
        }
        while(temp!=0&&temp%3==0){
            temp/=3;
        }
        while(temp!=0&&temp%5==0){
            temp/=5;
        }
        if(temp!=0){
            if(isPrime(temp)){
                // printf("T %d temp%d\n",Set[i],temp);
                return false;
            }
            else{
                if(temp==1) return true;
                for(ll j=2;j*j<=temp;++j){
                    if(temp%j==0){
                        // if(temp<100)
                        // printf("temp%I64d j%I64d\n",temp,j);
                        if(isPrime(j)) return false;
                    }
                }
                return true;
            }
        }
        return true;
}
int main(){
    int i,j;
    Set.push_back(1);
    for(i=2;i<10000000;++i){
        if(jud(i)){
            Set.push_back(i);
        }
    }
    sort(Set.begin(),Set.end());
    for(i=0;i<1500;++i){
        printf("%d ",Set[i]);
    }
    printf("\n");
    printf("The 1500'th ugly number is %d",180625);
    return 0;
}

事实证明正确答案8e9。。。而这个枚举1e7就要跑非常久。。

gg

事实上还没法证明检验条件是否正确

然后我们发现。。丑数可以由已有的丑数再加上丑数*2,3,5所新生成的丑数。。

但是如果你暴力乘法直接map记录出没出现过的数字。。没出现的话直接push

然后我们发现这样。。会漏掉中间的一些数字。。

但是下一轮操作我发现前面的一组数据

1 2 3 4 5 6 8 9 10 15 25再下一轮会加上12

年轻地认为只要取得足够靠后就能补全。。

事实上。。我后来花了大力气去逼近long long 的最大值来逼近。。

答案还是错的。。

那么我们可以理解为。。还有没补上的数字(如果答案输出格式没有问题的话)

那么怎么做比较稳妥呢?

对于第一个数特殊情况我们在集合S push 1

2,3,5乘一遍

2,3,5

取最小的没有出现过的push2

序列变成了1,2

2,3,5乘法一遍

2:2,4

3: 3,6

5: 5,10

我们在这六个数里取最小的。。

重复以上的步骤。。

最后我们得到的序列就是最小的。。

以后碰到中间缺项的时候。。我们可以用每次只取最小的1个!来完成取出完整的连续序列

其实我本来也是这么想的。。

但是我的写法和想法不是一致的。。这个在以后一定要多检查。。你的语句是否在做你期望的事情

下面贴上代码。。

ps q巨今天说对于PE返回WA。。热身赛测一下空格和回车就好了

对于64位整数。。有的评测机不支持%I64d的话。。可能会返回64个空格

但是现在大部分的评测机应该都支持%lld..

比赛的时候最好测试一下。。。

#include <iostream>
#include <cstdio>
#include <vector>
#include <map>
#include <algorithm>
using namespace std;
typedef long long ll;
vector<ll> S;
map<ll,ll> mp;
int p[]={2,3,5};
int n;
int main(){
    scanf("%d",&n);
    S.push_back(1);
    int i,j,flag=0;
    while(S.size()<n&&!flag){
        int sz=S.size();
        vector<ll> k;
        for(i=0;i<sz&&!flag;++i){
            ll t=S[i];
            for(j=0;j<3;++j){
                if(mp[p[j]*t]==0){
                    k.push_back(p[j]*t);
                }
            }
        }
        sort(k.begin(),k.end());
        S.push_back(k[0]);
        mp[k[0]]++;
    }    
    sort(S.begin(),S.end());
    printf("The 1500'th ugly number is 859963392.");
    return 0;
}

最后的输出是算好的1500th结果。。输入是丑数的规模。。

一开始做这个题还有一个错误的想法。。

我算的答案是用2,3,5,6,20,15,30作为基数去乘以不是质数的数来得到答案。。

但是。。不是质数的数仍然可能含有除了2,3,5以外的质因子

所以我们要把这种数排除掉。。于是就有了大暴力检验的模拟。。

8e9。。跑死你个智障。。。

posted @ 2016-12-08 22:56  狡啮之仰  阅读(933)  评论(0编辑  收藏  举报