Codeforces Round 1006 (Div. 3)
题目
题目大意就是给定一个十进制数将其分别转化为2-p进制数后,将该数逆置,然后转为对应的十进制,结果即是这些十进制数的和。
可考虑3种情况:
1.当时直接暴力枚举
2.当时,答案为
3.当时 可以发现转换成对应进制后长度只有两位
可得 ,
故总和形如下面的式子
化简得
然后就是对于这三块分别进行求解,可以用到整除分块
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int mod = 1e9 + 7;
int n, k;
int check(int x)//暴力枚举
{
int tn = n;
vector<int> v;
while (tn > 0)
{
v.push_back(tn % x);
tn /= x;
}
int ans = 0;
for (int i = 0; i < v.size(); i++)
{
ans = ans * x + v[i];
ans %= mod;
}
return ans;
}
int p(int x)//连续自然数的平方和
{
return x * (x + 1) * (2 * x + 1) / 6 % mod;
}
int sq(int l, int r)
{
if (l > r)
return 0;
int ans = (l + r) * (r - l + 1) / 2 % mod * n % mod;//n*p部分总和
int tl;
for (; l <= r; l = tl + 1)//分块
{
tl = n / (n / l);
tl = min(r, tl);//右界
ans = (ans + (tl - l + 1) * (n / l) % mod - (n / l) * (p(tl) - p(l - 1)) % mod + mod) % mod;
}
return ans;
}
void solve()
{
cin >> n >> k;
int ans = 0;
int o = sqrt(n);
int i = 2;
for (; i <= min(o, k); i++)
{
ans = (ans + check(i)) % mod;//2-min(o,k)部分,直接进行转换
}
ans += sq(i, min(n, k));//sqrt(n)-min(n,k)部分
ans = (ans + (k - min(n, k)) % mod * n % mod) % mod;//当进制大于n时
cout << ans % mod << endl;
}
signed main()
{
int T = 1;
cin >> T;
while (T--)
{
solve();
}
return 0;
}