擅长计算的小明对数字很感兴趣,关于计算方面的都很在行。不过现在他遇到了一个难题:他想区间[L,R]内所有数的各个位之和,我想这肯定难不倒你,那么如果让你求所有数在k进制表示下的各个位之和呢?你能帮他吗?
- 输入
- 多组测试数据(不超过10000组).
每行有三个数字L,R,k(0<=L<=R<10^15,k<=20).
这题思路不是问题,我调试了大半天才搞出来,一般的计数问题,要是比赛碰上了,肯定做不出
代码:
#include <iostream>
#include <cstring>
using namespace std;
typedef long long LL;
LL dp[100][21],ans[100];
LL pp(LL x,LL n)
{
LL s = 1;
while(n)
{
if(n & 1)
s *= x;
x *= x;
n >>= 1;
}
return s;
}
void inti(int k,int v)
{
memset(dp,0,sizeof(dp));
memset(ans,0,sizeof(ans));
ans[0] = 1;
for(int i = 0;i < k;i ++)
{
dp[1][i] = i;
ans[1] += i;
}
for(int i = 2;i <= v;i ++)
{
for(int j = 0;j < k;j ++)
{
for(int p = 0;p < k;p ++)
dp[i][j] += dp[i - 1][p];
dp[i][j] += pp(k,i - 1) * j;
}
for(int j = 1;j < k;j ++)
ans[i] += dp[i][j];
}
for(int i = 2;i <= v;i ++)
ans[i] = ans[i] + ans[i - 1];
}
LL f(LL x,LL k)
{
if(x == 0) return 0;
int a[100],v = 0;
while(x)
{
a[v ++] = x % k;
x /= k;
}
inti(k,v - 1);
LL sum = 0;
for(int i = v - 1;i >= 0;i --)
{
if(i > 0)
{
LL s = 0;
for(int j = v - 1;j > i;j --)
s += a[j];
sum += a[i] * pp(k,i) * s;
sum += a[i] * ans[i];
for(int j = 1;j < a[i];j ++)
sum += j * pp(k,i);
}
else
{
LL s = 0;
for(int j = v - 1;j > 0;j --)
s += a[j];
for(int j = 1;j < a[i];j ++)
sum += j;
sum += s * a[i];
}
}
return sum;
}
LL fun(LL x,LL k)
{
LL s = 0;
while(x)
{
s += x % k;
x /= k;
}
return s;
}
int main()
{
LL l,r,k,x,y;
while(cin >> l >> r >> k)
{
x = f(l,k);
y = f(r,k);
cout << y - x + fun(r,k) << endl;
}
return 0;
}