题目意思大概是给你w,m,k三个数,让你从m开始找 m m+1 m+2 m+3...........m+m', 使得他们的权值之和不超过w,计算权值的方法如下S(n)·k 。 S(n)表示n有多少位数,让你计算出最多有多少个这样的数。
乍一眼看去,10^16如此大的数肯定不能暴力,然后稍微思考一下就可以找到规律了,规律如下。
1-10 有9个一位数
1-100 有9个一位数 有90个二位数
1-1000 有9个一位数 有90个二位数 有900个三位数
1-10000 有9个一位数 有90个二位数 有900个三位数 有9000个四位数
。。。。。。。。。。。。
那么1-n有多少个几位数很快就可以计算出来了,然后用二分法计算结果。代码如下
#include <stdio.h>
#include <iostream>
#define ll long long
#define inf 100000000000000000
//二分上界必须大于10^16,不然会出错
using namespace std;
ll w, m, k;
ll getans(ll x)
{
ll cmp = 10;
ll add = 9;
ll ans = 0;
ll sum = 0;
ll cnt = 1;
while (x >= cmp)
{
sum += add;
ans += add*cnt;
cnt++;
add *= 10;
cmp *= 10;
}
ans += (x - sum)*cnt;
return ans;
}
inline ll getval(ll x)
{
return (getans(x)-getans(m-1));
}
ll binarysearch(ll l, ll r, ll val)
{
if (l == r)
{
while (getval(l) > val)
l--;
return l;
}
ll mid = (l + r) >> 1;
if (getval(mid) < val)
return binarysearch(mid+1, r, val);
else
return binarysearch(l, mid, val);
}
int main()
{
while (cin >> w >> m >> k)
{
ll t = binarysearch(m, inf, w/k);// 二分的第三个参数必须这样,不能在其他地方乘,不然也会溢出
if (t < m)
puts("0");
else
cout << t - m + 1 << endl;
}
return 0;
}