P14605 [NWRRC 2025] Faulty Fraction

· · 题解

UPD on 2025/11/27:修复了很莫名其妙的错误。

生活常识题。

注:\ell(a) 为数 a 的长度,例如 \ell(11)=2,\ell(5)=1

1. 题目分析

首先很显然的枚举 s 的分割点,判断 s 前半部分 a 和后半部分 b 是否满足 a=b\times c。但我们观察到 \ell(s) 很大,不能使用普通的整数运算,而普通高精乘法又限于 O(\ell(s)^2) 的超高复杂度,无法通过。

运用人类智慧。回顾乘法列竖式的过程,我们不难观察到若 b\times c 最高位不进位,那么就会有 \ell(a)=\ell(b)+\ell(c)-1,即 a 长度等于 b 的长度加上 c 的长度减一,例如 42\times 2=84,100\times 100=10000。那么若最高位进位了,也有 \ell(a)=\ell(b)+\ell(c),例如 6\times 5=30,999\times 999=998001

由于我们已经知道了 sc 的长度,且 \ell(a)+\ell(b)=\ell(s)\to\ell(a)=\ell(s)-\ell(b)\in\{\ell(b)+\ell(c)-1,\ell(b)+\ell(c)\},那么 \ell(b)=(\ell(s)-\ell(c)+1)/2\ell(b)=(\ell(s)-\ell(c))/2。注意到题目一定有解,同时除法会下取整,所以当 \ell(s)-\ell(c) 为偶数时,解精确地可以取两个,为奇数的时候只能取前面一个,整合起来,统一取前面一个。

基本上是 \text{substr} 的复杂度 O(\ell(s)) 的,代码很搞笑。

2. 代码

#include<bits/stdc++.h>
using namespace std;
int main()
{
    string s,c;
    cin>>s>>c;
    int n=s.size(),m=c.size(),k=(n-m+1)/2;
    cout<<s.substr(0,n-k)<<" "<<s.substr(n-k);
    return 0;
}