Project Euler 26-30题

第26题

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

这一题是求 1i,i[2,1000) 的所有结果的十进制小数表示下具有最长循环节的 i
我将在我的算法中定义有限小数也是循环节为1的循环小数,例如0.25=0.25(0)
回忆列竖式的过程,不太会用mathtype,没对齐,不过应当容易看懂。
这里写图片描述
在竖式的最后一行,我们出现了10,而10已经在竖式中出现过一次了,那么这就是一个循环节了。
我们在程序中模拟做竖式的过程,每次将(余数*10)加入set,若过程中发现该结果已经在set中了,则得到循环节长度。利用max_element输出最大值即可。
代码如下:

set<int> s[1000];
int len[1000];

int main(){
    int n=1000;
    for (int i=1;i<n;i++){
        int remain=1;
        while(s[i].count(remain)==0){
            s[i].insert(remain);len[i]++;
            remain=(remain%i)*10;
        }
    }
    cout<<*max_element(len,len+n)<<endl;
    return 0;
}



第27题

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

这个题是寻找函数 f(n)=n2+an+b 的一组 (a,b) ,满足 f(n)=prime,n[0,x) ,若 |a|<1000,|b|<1000 ,求当 x 取得最大值时的ab的值。
我没有想到很好的剪枝方法。我的思路是由于 f(0)=prime=b ,所以 b 一定是质数。a则是全部枚举一遍。

int main(){
    cnt=0;
    for (int i=2;i<=maxn;i++){
        if (num[i]==0)  p[++cnt]=i;
        for (int j=1;j<=cnt&&p[j]*i<maxn;j++){
            num[p[j]*i]=1;
        }
    }
    int maxx=0,ans=0;
    for (int a=-999;a<=999;a++){
        for (int index=1,b=p[index];b<=1000;index++,b=p[index]){
            if(a+b>=2){
                int tmp=cal(a,b);
                if (maxx<tmp)  {
                    maxx=tmp,ans=a*b;
                }
            }
        }
    }
    cout<<ans<<endl;
    return 0;



第28题

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

这个题是求1001*1001大小的方阵中,各数字如图排列,求对角线和。
除最中心的1以外,第i圈第j位置的数x与第i-1圈对应位置的数y的关系是 x=y+i82j ,其中将右上、左上、左下、右下的位置依次记为0,1,2,3;
而通过循环递推来完成更容易实现,记录一个add变量,每次将内圈的值加上add就得到了外圈的值。add每次自增2;

int main(){
    int f[4]={1,1,1,1};
    long long ans=1,n=500;
    for (int i=1,add=2;i<=n;i++){
        for (int j=0;j<4;add+=2,j++){
            f[j]+=add;
            ans+=f[j];
        }
    }
    cout<<ans<<endl;
    return 0;
}



第29题

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

题意如图。
求出所有的 (xymod1000000007,xymod1000000009) ,可以通过递推实现,将数对塞入set,最后统计set的元素个数。

pair<long long,long long>num[110][110];
long long mod1=1e9+7,mod2=1e9+9;
set<pair<long long,long long> > s;
int main(){
    int n=100;
    for (int i=2;i<=n;i++){
        num[i][1].first=num[i][1].second=i;
        for (int j=2;j<=n;j++){
            num[i][j].first=num[i][j-1].first*i%mod1;
            num[i][j].second=num[i][j-1].second*i%mod2;
            s.insert(num[i][j]);
        }
    }
    cout<<s.size()<<endl;
    return 0;
}



第30题

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

求所有除一以外自身等于各位数字的五次方和的数的和。考虑到 99=59049 ,所以满足条件的数一定小于 599=295245 。枚举每个数验证即可,复杂度 O(nlogn)

int check(int num){
    int ans=0;
    while(num){
        int x=num%10;
        ans+=x*x*x*x*x;
        num/=10;
    }
    return ans;
}

int main(){
    int ans=0;
    for (int i=2;i<=295245;i++){
        if (check(i)==i)    ans+=i;
    }
    cout<<ans<<endl;
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值