惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

AI
AI
G
Google Developers Blog
T
Tailwind CSS Blog
大猫的无限游戏
大猫的无限游戏
量子位
月光博客
月光博客
美团技术团队
阮一峰的网络日志
阮一峰的网络日志
罗磊的独立博客
T
The Exploit Database - CXSecurity.com
C
CXSECURITY Database RSS Feed - CXSecurity.com
Latest news
Latest news
P
Privacy International News Feed
www.infosecurity-magazine.com
www.infosecurity-magazine.com
WordPress大学
WordPress大学
博客园 - 三生石上(FineUI控件)
TaoSecurity Blog
TaoSecurity Blog
Hacker News: Ask HN
Hacker News: Ask HN
Hugging Face - Blog
Hugging Face - Blog
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
C
Cisco Blogs
Project Zero
Project Zero
Security Latest
Security Latest
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
人人都是产品经理
人人都是产品经理
Scott Helme
Scott Helme
S
Securelist
有赞技术团队
有赞技术团队
T
Threat Research - Cisco Blogs
N
News | PayPal Newsroom
博客园 - 聂微东
小众软件
小众软件
S
SegmentFault 最新的问题
D
Darknet – Hacking Tools, Hacker News & Cyber Security
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
P
Privacy & Cybersecurity Law Blog
博客园 - Franky
Cyberwarzone
Cyberwarzone
Cisco Talos Blog
Cisco Talos Blog
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
Spread Privacy
Spread Privacy
A
Arctic Wolf
S
Security @ Cisco Blogs
The Hacker News
The Hacker News
腾讯CDC
博客园 - 【当耐特】
T
Troy Hunt's Blog
NISL@THU
NISL@THU
爱范儿
爱范儿

博客园 - 申龙斌的程序人生

将博客搬至CSDN 读书:有钱人想的和你不一样 读书打卡:《微信互联网平民创业》 用欧拉计划学Rust编程,第323题,随机整数按位或运算 《老喻的人生算法课》读书笔记之A计划 利用欧拉计划学Rust编程(第493题) 用欧拉计划学Rust编程(第61题) 通过欧拉计划学Rust编程(第500题) - 申龙斌的程序人生 - 博客园 申龙斌的读书笔记(2011-2019) 通过欧拉计划学Rust编程(第54题) - 申龙斌的程序人生 - 博客园 刷完欧拉计划中难度系数为5%的所有63道题,我学会了Rust中的哪些知识点? - 申龙斌的程序人生 - 博客园 用欧拉计划学Rust编程(第26题) 通过欧拉计划学习Rust编程(第22~25题) 用欧拉计划学Rust语言(第17~21题) 用欧拉计划学习Rust编程(第13~16题) 用欧拉计划学Rust语言(第7~12题) 通过欧拉计划学Rust(第1~6题) 《区块链生存训练2.0》PDF 写书,我是认真的,但我真不知道能否财富自由
用欧拉计划学Rust编程语言(第700题:Eulercoin)
申龙斌的程序人生 · 2020-06-06 · via 博客园 - 申龙斌的程序人生

问题描述:
欧拉诞生于1707年4月15日,对于序列(1504170715041707 * n) mod 4503599627370517,如果一个元素小于前面发现的所有Eulercoin,则其称为Eulercoin。

例如,第一个元素是1504170715041707,为第一个Eulercoin,第二个元素为3008341430083414,由于它大于1504170715041707,所以不是Eulercoin。然而,第三个元素为8912517754604,比前面的数都小,被称为Eulercoin。前两个Eulercoins之和是1513083232796311。

求所有Eulercoin之和。

解题过程:

第一步,先根据题意暴力求解

这个代码非常容易写出来。

const INC: u64 = 1504170715041707_u64;
const MOD: u64 = 4503599627370517_u64;

let mut x = 0_u64;
let mut min = INC;
for n in 1_u64.. {
    x = (x + INC) % MOD;
    if x <= min {
        min = x;
        println!("{:20} {:20}", n, x);
    }
}

运行这个程序,可以输出如下结果。

                   1     1504170715041707
                   3        8912517754604
                 506        2044785486369
                2527        1311409677241
                4548         578033868113
               11117         422691927098
               17686         267349986083
               24255         112008045068
               55079          68674149121
               85903          25340253174
              202630           7346610401
              724617           4046188430
             1246604            745766459
             6755007            428410324
            12263410            111054189
            42298633             15806432
           326125654             15397267
           609952675             14988102
           893779696             14578937
          1177606717             14169772
          1461433738             13760607
          1745260759             13351442
          2029087780             12942277
          2312914801             12533112
          2596741822             12123947
          2880568843             11714782
          3164395864             11305617
          3448222885             10896452
          3732049906             10487287
          4015876927             10078122
          4299703948              9668957
          4583530969              9259792
          4867357990              8850627
          5151185011              8441462
          5435012032              8032297
          5718839053              7623132
          6002666074              7213967
          6286493095              6804802
          6570320116              6395637
          6854147137              5986472
          7137974158              5577307
          7421801179              5168142
          7705628200              4758977
          7989455221              4349812
          8273282242              3940647
          8557109263              3531482
          8840936284              3122317
          9124763305              2713152
          9408590326              2303987
          9692417347              1894822
          9976244368              1485657
         10260071389              1076492
         10543898410               667327
         10827725431               258162
             … … … …              … … … …

越往后,想找到一个Eulercoin愈发困难,必须得改进算法。

第二步,找规律

在n=2527之后,后一个eulercoin与前一个eulercoin有着递推的关系,补上一些数字之后,就能发现更为明显的关系。比如,n=2021, 6569, 30824, 116727…时,得到的数虽然不是eulercoin,但数值非常大,与4503599627370517越来越接近。

根据发现的规律,需要保存好最小的数和最大的数,不用一个数一个数的计算,效率非常高,不到1秒计算完成。

let mut sum = 1504170715041707_u64 + 8912517754604_u64 + 2044785486369_u64 + 1311409677241_u64;
let mut n_max = 2021_u64;
let mut max = 4502866251561389_u64;
let mut n = 2527_u64;
let mut x = 1311409677241_u64;
let mut min = x;

while min > 0 {
    let temp_n = n + n_max;
    let temp_x = (x + max) % 4503599627370517_u64;
    if temp_x <= min {
        n = temp_n;
        x = temp_x;
        min = x;
        sum += x;
        println!("{:20} {:12} {:20}", n, x, sum);
    }
    if temp_x > max {
        n_max = temp_n;
        max = temp_x;
        //println!("max: {} {} ", n_max, max);
    }
}

再优化

看了欧拉论坛中的优秀贴子,发现n的索引值并不需要记录,代码还可以更优美一些。

let inc = 1504170715041707_u64;
let modular = 4503599627370517_u64;
let mut low = inc;
let mut high = inc;
let mut sum = inc;
while low > 0 {
    let next = (low + high) % modular;
    if next < low {
        low = next;
        sum += low;
        println!("{:20} {:20}", low, sum);
    } else {
        high = next;
    }
}
println!("{}", sum);