USACO2024DEC铜组T1
首先,我们先看 \(99\) 中会约错的数字
显然有 \(45\) ~ \(49\),\(5\) 个
然后,我们再看 \(100\) ~ \(999\) 中会约错的数字
显然有 \(445\) ~ \(499\),\(55\) 个
然后,我们再看 \(1000\) ~ \(10000\) 个中会约错的数字
显然有 \(4445\) ~ \(4999\),\(555\) 个
由此,我们可以得出结论:在 \(10^n\) ~ \(10^{n + 1} - 1(n \ge 1)\) 中,总共有 \(\displaystyle\sum^{n}_{i=1}(5*10^{i - 1})\) 个数字会被约错,而在 \(2\) ~ \(9\) 中没有数字会被约错
不严谨的证明:
拿 \(1000\) ~ \(9999\) 来说
如果某一个数小于 \(4445\),那么无论是四舍五入还是链式舍入,显然都会约到 \(0\)
而如果一个数大于 \(4999\),那么这两种舍入的方式都会约到 \(10000\)
于是,我们可以对于给定的 \(n\),先找到一个最大的整数 \(k\),使得 \(10^k-1\le n\),然后统计 \(2\) ~ \(10^k-1\) 中的所有 \(10^i\) ~ \(10^{i + 1} - 1\) 的答案个数相加
然后,再判断一下 \(n\) 是否在 \(10^k\) ~ \(10^{k+1}-1\) 中可能出现约错的区间内:如果小于,则答案不用再做处理;如果在区间内,则答案加上部分会约错的数;如果大于,则答案加上全部会约错的数
点击查看代码
#include <iostream>
#include <cmath>
#define int long long
using namespace std;
const int maxn = 15;
long long ge[maxn];
signed main()
{
ge[0] = 0;
ge[1] = 0;
for (int i = 2; i <= 9; ++i)
{
for (int j = 1; j <= i - 1; ++j)
{
ge[i] = ge[i] * 10 + 5;
}
}
// 统计每一个10^i~10^{i+1}-1区间的答案个数
int t;
cin >> t;
while (t--)
{
int n;
cin >> n;
if (n <= 10)
{
cout << 0 << '\n';
continue;
}
//这里直接特判
int d = n;
int cnt = 0;
while (d)
{
++cnt;
d /= 10;
}
cnt--;
int ans = 0;
for (int i = 1; i <= cnt; ++i)
{
ans += ge[i];
}
// 统计所有出现的区间的答案总和
int m = 0;
for (int i = 1; i <= cnt; ++i)
{
m = m * 10 + 4;
}
m = m * 10 + 5;
if (n >= m && n < 5 * pow(10, cnt))
{
ans += n - m + 1;
}
else if (n >= 5 * pow(10, cnt))
{
ans += ge[cnt + 1];
}
// 判断是否在可能约错的区间之下/之中/之上
cout << ans << '\n';
}
return 0;
}

浙公网安备 33010602011771号