专栏文章

题解:P3922 中学数学题

P3922题解参与者 6已保存评论 10

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
10 条
当前快照
1 份
快照标识符
@miojiuuv
此快照首次捕获于
2025/12/02 20:14
3 个月前
此快照最后确认于
2025/12/02 20:14
3 个月前
查看原文

P3922 中学数学题 题解


这中学数学题?
题意还是很明了的,一看就明白,不再赘述。
其实笔者看到这题就想暴力。
但是在看到难度和数据范围时不舍地捏碎了我的暴力梦。
解密输入后发现 kk 最大是 1023310^{233},根据通项公式,得到数列中可能的最大值为 2102332^{10^{233}} 果断放弃暴力。
极大的数据启示我们寻找规律。

Part 1:规律:

先贴上找规律用的代码:

code1:

CPP
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>

using namespace std;

// 乘2
string multwo(const std::string& num) {
    string result;
    int carry = 0;
    
    for (int i = num.size() - 1; i >= 0; --i) {
        int digit = (num[i] - '0') * 2 + carry;
        result.push_back(digit % 10 + '0');
        carry = digit / 10;
    }
    
    // 处理进位
    while (carry > 0) {
        result.push_back(carry % 10 + '0');
        carry /= 10;
    }
    
    // 反转结果字符串以获得正确顺序
    reverse(result.begin(), result.end());
    return result;
}

int main() {
    string current = "1";
    
    // 计算并输出2的1到10000次幂
    for (int i = 1; i <= 10000; ++i) {
        // 输出当前幂次和结果
        cout << "2^" << i << " = " << current << std::endl;
        
        // 计算下一个幂次
        current = multwo(current);
        
    }
    
    return 0;
}    
使用这段代码输出 22111000010000 次幂,开始找规律。
为了方便讲解,我把前 5050 行输出粘贴到下面:
CPP
2^1 = 1
2^2 = 2
2^3 = 4
2^4 = 8
2^5 = 16
2^6 = 32
2^7 = 64
2^8 = 128
2^9 = 256
2^10 = 512
2^11 = 1024
2^12 = 2048
2^13 = 4096
2^14 = 8192
2^15 = 16384
2^16 = 32768
2^17 = 65536
2^18 = 131072
2^19 = 262144
2^20 = 524288
2^21 = 1048576
2^22 = 2097152
2^23 = 4194304
2^24 = 8388608
2^25 = 16777216
2^26 = 33554432
2^27 = 67108864
2^28 = 134217728
2^29 = 268435456
2^30 = 536870912
2^31 = 1073741824
2^32 = 2147483648
2^33 = 4294967296
2^34 = 8589934592
2^35 = 17179869184
2^36 = 34359738368
2^37 = 68719476736
2^38 = 137438953472
2^39 = 274877906944
2^40 = 549755813888
2^41 = 1099511627776
2^42 = 2199023255552
2^43 = 4398046511104
2^44 = 8796093022208
2^45 = 17592186044416
2^46 = 35184372088832
2^47 = 70368744177664
2^48 = 140737488355328
2^49 = 281474976710656
2^50 = 562949953421312
统计了开头各数字出现次数后,发现以 44 为开头的项较少,考虑通过其他开头数字出现的规律来求解。
观察到以 11 为开头的数字有很多,不妨考虑以 11 为开头的数字。
将开头数字单独摘出:
1,2,4,8,1{\color{blue}1} , 2 , {\color{red}4} , 8 , {\color{blue}1}
1,3,6,1{\color{blue}1} , 3 , 6 , {\color{blue}1}
1,2,5,1...{\color{blue}1} , 2 , 5 , {\color{blue}1} ...
发现 11 好像在循环。
继续往下找,又发现两种以 11 开头,结尾的序列:
1,3,7,1{\color{blue}1} , 3 , 7 , {\color{blue}1}
1,2,4,9,1{\color{blue}1} , 2 , {\color{red}4} , 9 , {\color{blue}1}
按字典序排列后:
1,2,4,8,1{\color{blue}1} , 2 , {\color{red}4} , 8 , {\color{blue}1}
1,2,4,9,1{\color{blue}1} , 2 , {\color{red}4} , 9 , {\color{blue}1}
1,2,5,1{\color{blue}1} , 2 , 5 , {\color{blue} 1}
1,3,6,1{\color{blue}1} , 3 , 6 , {\color{blue}1}
1,3,7,1{\color{blue}1} , 3 , 7 , {\color{blue}1}
奇怪的事情发生了。
我们暂且称上面几种序列为“循环段”,用 cic_i 表示,值为原数列中 listilist_i 的最高位的值。
顺便定义由 listilist_i 得到 cic_i 的函数:
f(x)=x10logxf(x) = \lfloor {\frac{x}{10^{\log x}}} \rfloor
代入 listilist_icic_i 得:
ci=f(listi)=listi10loglistic_i = f(list_i) = \lfloor {\frac{list_i}{10^{\log list_i}}} \rfloor
(注:此处 logx\log {x} 均为以十为底的对数,即 log10x\log_{10} x,考虑可读性不在定义式中加入。)
发现:
段长为 55 时,段中出现一个 44
段长为 44 时,段中不出现 44
在笔者往下看了几百行数字后,更确信此结论的正确性。

Part 2:证明:

命题:循环段长度为 454 \mid 5, 且仅有如上 55 种:

因为原数列中每项都等于前一项 ×2\times 2
所以每个数位都应 == 前一位 ×2\times 2 (竖式乘法计算步骤)。
若段长为 55
c5c_5 对应的项的前两位应为此循环段中第一个 10\ge 10 的数。
根据循环段定义 (首尾为 11 ):
则此循环段的 c4c_4 一定不是 11
即原数列这一项开头不是 11
考虑由 c1c_1 得到 c5c_5 的情况:
每次 ×2\times 2,对吧?
又因为第一位为 11 , 考虑进位最多的情况:
2752^{75} ~ 2792^{79}
CPP
2^75 = 18889465931478580854784
2^76 = 37778931862957161709568
2^77 = 75557863725914323419136
2^78 = 15115727451828646838272
2^79 = 302231454903657293676544
发现每次进位都是先 ×2\times 2+1+ 1
不进位仅 ×2\times 2
所以:
c1=1c2=23c3=4567c4=891c5=1c_1 = 1\\ c_2 = 2 \mid 3 \\ c_3 = 4 \mid 5 \mid 6 \mid 7\\ c_4 = 8 \mid 9 \mid 1 \\ c_5 = 1
c4c_4 的值为 1891 \mid 8 \mid 9,而 无论 c4c_4 取何值,经过扩展后的 c5c_5 值只有一个:11
根据循环段的定义,段长最大为 55
又因为 c4c_4 是循环段中第一个可能出现 11 的单位,
所以段长最短为 44
根据 c1c_1c5c_5 的值及进位规律,易得到下面这张表:
111
上图中红边代表不进位且得到的 ci+1<10c_{i+1} < 10,也可理解为 f(ci+1)=ci+1f(c_{i+1}) = c_{i+1}
蓝边代表进位且得到的 ci+1<10c_{i+1} < 10, 即 f(ci+1)=ci+1f(c_{i+1}) = c_{i+1}
绿边代表得到的 ci+110c_{i+1} \ge 10,也即 f(ci+1)=1f(c_{i+1}) = 1
由上文定义可知:
\quad 绿边后必连接 11,当遇到绿边时,说明循环段结束。
图中共有 55 条绿边,说明前文定义的循环段形式有限,数量为 55 种。
顺着红蓝边查找路径,将路径经过的点按顺序排列后发现:
1,2,4,8,1{\color{blue}1} , 2 , {\color{red}4} , 8 , {\color{blue}1}
1,2,4,9,1{\color{blue}1} , 2 , {\color{red}4} , 9 , {\color{blue}1}
1,2,5,1{\color{blue}1} , 2 , 5 , {\color{blue} 1}
1,3,6,1{\color{blue}1} , 3 , 6 , {\color{blue}1}
1,3,7,1{\color{blue}1} , 3 , 7 , {\color{blue}1}
所以,循环段的长度为 454 \mid 5,且是上文列出的 55 种情况之一。
证毕。
大佬们觉得罗嗦轻点喷啊!求求了!
这部分是给和笔者一样的蒟蒻们理清思路而写的。
(俺一下午才明白),有错误欢迎指出!

Part 3: 题目解法:

我们已经将这个等比数列划分成了几个循环段的拼接。
因为循环段开头结尾都为 11,不好处理,舍弃最后一个 11,记作 newcnewc
1,2,4,81 , 2 , {\color{red}4} , 8
1,2,4,91 , 2 , {\color{red}4} , 9
1,2,51 , 2 , 5
1,3,61 , 3 , 6
1,3,71 , 3 , 7
观察到对于每一个 newcnewc,当长度为 44 时,其中必然包含 1144
不妨设序列的前 k+1k+1 项中有 xx 个循环段满足此段项数为 44,即上两种。
可以发现,2i2^i 若发生了进位,那么 2i+12^{i+1} 的位数将会多 11
找到满足 kk+1k' \le k+12k=12^{k'} = 1 的最大的 kk'
2^k' 共有 mm 位。
考虑 2k2^{k'} 时共发生了几次进位即 m1m-1
观察到循环段与进位的关系:
1,2,4,81 , 2 , {\color{red}4} , 8 \quad 不进位
1,2,4,91 , 2 , {\color{red}4} , 9 \quad 进位 11
1,2,51 , 2 , 5 \quad 进位 11
1,3,61 , 3 , 6 \quad 进位 11
1,3,71 , 3 , 7 \quad 进位 22
相加后发现进位次数就等于循环段的个数。
就可以求出段长为 33 的段数的个数:(m1x)(m - 1 - x)
根据项数列方程可得:
4x+3(m1x)=k4x + 3(m-1-x) = k'
解得:
x=k3(m1)x = k' - 3(m - 1)
因为 mm2k2^{k'} 在十进制下的位数,所以:
m=klog102m = k' \log_{10} 2
就得到答案了。
纪念我的第一道紫题!
和我的第一道紫题题解!

评论

10 条评论,欢迎与作者交流。

正在加载评论...