[ARC052D] 9
题意翻译是假的,骗了我十分钟(恼)。
题目大意
给定两个正整数 \(k\) 和 \(m\),需要求出有多少个正整数 \(n\) 满足 \(1 \leq n \leq m\) 且 \(n \equiv S_n(\operatorname{mod} k)\)。
(\(1 \leq m \leq 10^{10}\))
思路
范围 \(10^{10}\),考虑根号复杂度。
考虑根号分治,设 \(T\) 在 \(\sqrt{m}\) 级别。
- \(K \geq T\)
容易发现,\(S_n\) 的值很小,最大也不会超过 \(90\)。
那我们可以枚举数字和 \(S_n\)。
那么与 \(S_n\) 关于 \(k\) 同余的 \(n\) 的个数不会超过 \(\left\lfloor \frac{m}{k} \right\rfloor + 1\) 个。
直接枚举这些 \(n\) 就可以了,复杂度达标。
- \(K < T\)
考虑把 \(n \operatorname{mod} k\) 的值作为一维放状态里,直接数位 DP 即可。
Code
// ARC052D
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 10500;
int n,m,k;
int dp[15][N][95][2];
// dp[i][j][k][l] :
// 第 i 位,Sn % k = j,Sn = k,是否为上界
int num[15],tot;
int dfs(int cnt,int mod,int sum,int lim) {
if(cnt == 0) {
if(mod == sum % k && sum != 0)
return 1;
return 0;
}
if(dp[cnt][mod][sum][lim] != -1)
return dp[cnt][mod][sum][lim];
int Max = 9,ans = 0;
if(lim)
Max = num[cnt];
for(int i = 0;i <= Max; i++)
ans += dfs(cnt - 1,(mod * 10 + i) % k,sum + i,lim && i == Max);
return dp[cnt][mod][sum][lim] = ans;
}
int Work(int x) {
while(x) {
tot ++;
num[tot] = x % 10;
x /= 10;
}
return dfs(tot,0,0,1);
}
signed main() {
cin >> k >> m;
memset(dp,255,sizeof(dp));
if(k <= 1e4)
cout << Work(m) << "\n";
else {
int ans = 0;
for(int i = 0;i <= 90; i++) {
for(int j = i;j <= m; j += k) {
int x = j,Sn = 0;
while(x) {
Sn += x % 10;
x /= 10;
}
if(Sn % k == i)
ans ++;
}
}
cout << ans - 1 << "\n";
// 去掉 0
}
return 0;
}