AtCoder Regular Contest 090 F - Number of Digits
2024-09-19 21:30:55
题目链接
Description
For a positive integer \(n\), let us define \(f(n)\) as the number of digits in base \(10\).
You are given an integer \(S(1≤S≤10^8)\). Count the number of the pairs of positive integers \((l,r)\) \((l≤r)\) such that \(f(l)+f(l+1)+…+f(r)=S\), and find the count modulo \(10^9+7\).
题解
分两种情况讨论。
\(1.\ f(l)\leq 7\)
则至多有\(10^8/8=12500000\)个八位数,所以\(r\leq 22500000\).
因此,可以预处理出\(f[1..22500000]\),然后采用 尺取法 得到 当\(f(l)\leq 7\)时 的\((l,r)\)组数.
\(2. \ f(l)\geq 8\)
此时,由 \(S\) 的限制,易知 \(f(r)-f(l)\leq 1\).
令 \(t=r-l+1\),枚举 \(t\)
若 \(f(l)==f(r)\)
则显然要求 \(t|S\),
记\(N\)位数的个数右 \(D_N\) 个,则符合要求的 \((l,r)\) 组数为 \(D_{\frac{S}{t}}-t+1\)
若 \(f(r)-f(l)==1\)
设 \(len=f(l)\) 且长度为 \(len\) 的数字有 \(x\) 个,长度为 \(len+1\) 的数字有 \(y\) 个,则有
\[\begin{cases}
x+y=t\\
x*len+y*(len+1)=S
\end{cases}
\]
x+y=t\\
x*len+y*(len+1)=S
\end{cases}
\]
其中\(len=\lfloor\frac{S}{t}\rfloor\).
记\(S=tq+r\ (0\leq r\lt t)\)
则方程组可转化为
\[\begin{cases}
x+y=t\\
xq+y(q+1)=tq+r
\end{cases}
\]
x+y=t\\
xq+y(q+1)=tq+r
\end{cases}
\]
所以有
\[\begin{cases}
x=t-r=t-S\%t\\
y=r=S\%t
\end{cases}
\]
x=t-r=t-S\%t\\
y=r=S\%t
\end{cases}
\]
即对每个\(t\)此时有且仅有一组解。
统计上述三部分的答案,即为最终答案。
Code
#include <bits/stdc++.h>
#define lim1 10000000
#define lim2 22500000
using namespace std;
typedef long long LL;
int f[lim2+10];
const LL mod = 1e9+7;
void init() {
int l = 1, r = 10;
for (int k = 1; k <= 7; ++k) {
for (int i = l; i < r; ++i) f[i] = k;
l = r; r *= 10;
}
for (int i = lim1; i <= lim2; ++i) f[i] = 8;
}
LL poww(LL a, LL b) {
LL ret = 1;
while (b) {
if (b & 1) (ret *= a) %= mod;
(a *= a) %= mod;
b >>= 1;
}
return ret;
}
LL count1(LL x) {
int l = 1, r = 1, ret = 0; LL sum = 0;
while (true) {
while (r <= lim2 && sum < x) sum += f[r++];
if (sum < x) break;
if (sum == x) (ret += 1) %= mod;
sum -= f[l++];
if (l == lim1) break;
}
return ret;
}
LL count2(LL x) {
LL upp = x/8,
ret = upp;
for (int t = 1; t <= upp; ++t) {
if (x % t == 0) {
int len = x / t;
LL sub = 9 * poww(10, len-1) % mod;
(sub += mod - t) %= mod;
(ret += sub) %= mod;
}
}
return ret;
}
int main() {
init();
LL n;
scanf("%lld", &n);
LL ans1 = count1(n), ans2 = count2(n);
printf("%lld\n", (ans1+ans2)%mod);
return 0;
}
最新文章
- 【转载】 postman使用教程
- Topcoder SRM 619 DIv2 500 --又是耻辱的一题
- struts2DMI(动态方法调用)
- 一款jQuery实现重力弹动模拟效果特效,弹弹弹,弹走IE6
- 简答的理解C语言中的各种类型函数
- 用PHP操作http中Etag、lastModified和Expires标签
- Linux下如何查看高CPU占用率线程 LINUX CPU利用率计算
- 超长英文(代码)自动换行的样式(CSS)
- Linux Kernel系列一:开篇和Kernel启动概要
- 浅谈android的selector,背景选择器
- SESSION会话技术
- Calendar使用方法
- HTML5文件操作API
- C学习笔记(逗号表达式)
- 移动开发的捷径:3种方式轻松创建webapp
- 【1】【leetcode-77】 组合
- css3 自定义滚动条样式
- 【kafka】设置指定topic和group_id消耗的offset
- meta中minimal-ui属性
- JAVA RSA私钥 加密(签名) 对应 C# RSA私钥 加密(签名)
热门文章
- setInterval与setTimeout
- 用express框架实现反向代理
- javascript隐藏和显示元素以及清空textarea
- UVa 1455 Kingdom 线段树 并查集
- loj2062 [HAOI2016]地图
- 【Best Time to Buy and Sell Stock II】cpp
- 【Combination Sum II 】cpp
- leetcode 【 Search in Rotated Sorted Array 】python 实现
- 【NOIP 2012】借教室
- python学习-- Django进阶之路 model的 objects对象 转 json