Project Euler 46-50题

第46题

这里写图片描述
题目来源ProjectEuler

这个题求满足如下条件的最小的数x:
1.是奇数
2.是合数
3.不能表示为 x=p+2y2 ,其中p为质数,y为正整数。
先筛出一个范围内的质数,比如1~100w,然后求其中的合数是否满足以上条件。
复杂度 O(nn)

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

const int maxn=1000000;
int num[maxn+1]={1,1},prime[maxn+1],cnt;

int main(){
    for (int i=2;i<=maxn;i++){
        if (num[i]==0)  prime[++cnt]=i;
        for (int j=1;j<=cnt&&i*prime[j]<=maxn;j++){
            num[i*prime[j]]=1;
        }
    }
    for (int i=35;;i+=2){
        if (num[i]==0)  continue;
        int boolean=0;
        for (int j=1;2*j*j<=i;j++){
            if (num[i-j*j*2]==0){
                boolean=1;
                break;
            }
        }
        if (!boolean){
            cout<<i<<endl;
            return 0;
        }
    }
}



第47题

这里写图片描述
题目来源ProjectEuler

这个题求连续的4个数的第1个数,要求这4个数每个数都恰好有4个质因子。
依然筛出前100w的质数,然后求每个数因子的个数,保存为fact,增加一个临时变量x,记录连续的质因子个数为4的数的个数,如果当期fact=4,x++,否则x=0;
当x=4的时候,输出i-3;

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

const int maxn=999999;
int prime[maxn+10],num[maxn+10],cnt;
int fact;

int main(){
    num[1]=0;
    for (int i=2;i<=maxn;i++){
        if (num[i]==0)  prime[++cnt]=i;
        for (int j=1;j<=cnt&&i*prime[j]<=maxn;j++){
            num[i*prime[j]]=1;
        }
    }
    int x=0;
    for (int i=1;i<=maxn;i++){
        int tmp=i;
        fact=0;
        for (int j=1;prime[j]*prime[j]<=tmp;j++){
            if (tmp%prime[j]==0)        fact++;
            while(tmp%prime[j]==0)  tmp/=prime[j];
        }
        if (tmp!=1)     fact++;
        if (fact==4)    x++;
        else            x=0;
        if (x==4){
            cout<<i-3<<endl;
            return 0;
        }   
    }
}



第48题

这里写图片描述
题目来源ProjectEuler

这个题求 1000i=1ii ,保留最后十位,即mod=10,000,000,000
由于unsigned long long只能保存大约1.8e19的整数,不利用高精度,无法直接使用快速幂求出结果。
但由于mod为 1010 ,通过对快速幂的一个简单的修改,不需要高精度也可以求出结果。
(ab)%mod=(a(b/100000)%mod100000+a(b%100000))%mod

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

const long long mod=10000000000;

long long fexp(long long x,long long y){
    long long ans=1,tmp;
    while(y){
        if (y&1){
            ans=ans*(x/100000)%mod*100000+ans*(x%100000);
            ans=ans%mod;
        }
        x=x*(x/100000)%mod*100000+x*(x%100000);
        x%=mod;
        y>>=1;
    }
    return ans;
}

int main(){
    long long n=1000;
    long long ans=0;
    for (long long i=1;i<=n;i++){
        ans+=fexp(i,i);
        ans%=mod;
    }
    cout<<ans<<endl;
    return 0;
}



第49题

这里写图片描述
题目来源ProjectEuler

这个题求这样三个四位质数,其中这三个质数构成等差数列且是同一组数字的不同排列。
例如题中给出的1487,4817,8147是公差为3330的等差数列,且是质数,是1,4,7,8的三个排列。
题目中告诉我们还有一组这样的四位数,要求找出来并且从小到大将他们连成一个12位数。
思路是枚举四个数字,对其所有排列进行check

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

int num[6];
int prime[10010],boolean[10010],cnt;

void check(){
    int x[25],cnt=0;
    for (int i=1;i<=24;i++){
        int tmp=0;
        for (int j=1;j<=4;j++){
            tmp=tmp*10+num[j];
        }
        if (!boolean[tmp]&&tmp>=1000)   x[++cnt]=tmp;
        next_permutation(num+1,num+5);
    }
    for (int i=1;i<=cnt;i++){
        for (int j=i+1;j<=cnt;j++){
            if (x[j]==x[i]) continue;
            for (int k=j+1;k<=cnt;k++){
                if(x[k]+x[i]==x[j]+x[j])
                    cout<<x[i]<<x[j]<<x[k]<<endl;
            }
        }
    }
}

int main(){
    boolean[1]=1;
    for (int i=2;i<=9999;i++){
        if (!boolean[i])    prime[++cnt]=i;
        for (int j=1;j<=cnt&&i*prime[j]<=9999;j++){
            boolean[i*prime[j]]=true;
        }
    }
    for (int i=0;i<=9;i++){
        num[1]=i;
        for (int j=i;j<=9;j++){
            num[2]=j;
            for (int k=j;k<=9;k++){
                num[3]=k;
                for (int l=k;l<=9;l++){
                    num[4]=l;
                    check();
                }
            }
        }
    }
    return 0;
}



第50题

这里写图片描述
题目来源ProjectEuler

有一些质数可以表示为若干个连续质数的和,比如 41=2+3+5+7+11+13
题目要求找出小于100w的质数中,能表示为最多质数和的那个质数。

对于100w以内的所有质数,枚举起点,一直求和,直到和大于100w为止。中途记录最长长度即达成该长度的sum值。
由于连续的求和,sum与长度len的关系大约是 sum>len22 ,所以复杂度大约为 O(nn) ,实际上快大约1个数量级。

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

const int n=1000000;
int num[n+1],prime[n+1],cnt;

int main(){
    for (int i=2;i<=n;i++){
        if (!num[i])    prime[++cnt]=i;
        for (int j=1;j<=cnt&&i*prime[j]<=n;j++){
            num[i*prime[j]]=1;
        }
    }
    int maxx=0,ans,sta;
    for (int i=1;i<=cnt;i++){
        int sum=0;
        for (int j=0;sum<n&&j+i<=cnt;j++){
            sum+=prime[i+j];
            if (maxx<j&&sum<n&&num[sum]==0){
                maxx=j;ans=sum;sta=i;
            }
        }
    }
    cout<<ans<<endl;
    return 0;
}



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值