问题描述
假设给定一个从l到r的范围,我们被要求找出所有数字都是x的倍数的数字的计数。 x可以是1到9之间的任何数字。例如,取l = 20和r = 40且x = 2,则所需的数字是20、22、24、26、28、40,因为x的倍数是0、2、4 ,6,8。
我已经为此编写了代码。它针对某些测试用例运行。我不知道为什么大多数测试用例都给出错误的答案。
约束:1
我的代码:
#include<bits/stdc++.h>
using namespace std;
#define ll long long int
ll s1(vector<string> &v,ll N)
{
ll i,j,n = v.size(),ans = 0;
string ss = "",s = "";
for (i = 0; i < n; i++)
{
s += v[i];
}
ss = to_string(N);
ll d = ss.length(),f = 0,x = n - 1,y = 1;
for (i = 1; i < d; i++)
{
if (i == 1)
{
ans += x;
y = x;
continue;
}
y = y * n;
ans += y;
}
ll z = 0;
for (j = 0; j < d; j++)
{
f = 0;
for (i = 0; i < s.length(); i++)
{
if (z == 0)
{
z++;
continue;
}
if (s[i] < ss[j])
{
ans += pow(n,d - (j + 1));
z++;
}
else if (s[i] == ss[j])
{
z++;
f = 1;
break;
}
}
if (!f)
{
break;
}
}
ans += f;
return and;
}
int main()
{
ios_base::sync_with_stdio(false);
cin.tie(NULL);
int t;
cin >> t;
while (t--)
{
ll l,r;
ll k,i,g;
cin >> l >> r >> k;
vector<ll> v1;
ll x = 0;
while (x <= 9)
{
v1.push_back(x);
x = x + k;
}
vector<string> s;
for (i = 0; i < v1.size(); i++)
{
g = v1[i];
char c = g + '0';
string d(1,c);
s.push_back(d);
// cout << D[i] << " ";
}
cout << s1(s,r) - s1(s,l - 1) << '\n';
}
}
有人可以告诉我这个问题的更好逻辑吗?
解决方法
- 使用动态编程,我们可以编写函数
f(x,d)
,该函数为我们提供范围[0,x]
中的数字,以使每个数字都是d
的倍数。 - dp状态:
[position in X][is our number prefix == X prefix?]
- 将使用
log10(X) * 2
空间 - 开始状态显然是
[0][1]
- 然后,我们只需填写dp表,使用递归尤其容易,在此我们只需检查可以添加的下一位数字即可满足所有条件
- 因此,如果我们删除常量,则此类dp函数的总复杂度将为
O(log10(X) * 2 * 10)
或仅为O(log N)
- 然后答案就是f(R,x)-f(L-1,x)
示例代码(C ++):
#include <bits/stdc++.h>
using namespace std;
#define ll long long
ll dp[22][2]; //[position in X][is our number prefix == X prefix?]
ll do_dp(vector<int>&digits,int k,int pos = 0,bool isEq = true)
{
if(pos >= digits.size())return 1;
if(dp[pos][isEq] != -1)return dp[pos][isEq];
dp[pos][isEq] = 0;
for(int d = 0; d <= (isEq ? digits[pos] : 9); d++) //d is next digit
if(d % k == 0) //multiple of k
dp[pos][isEq] += do_dp(digits,k,pos+1,isEq && d == digits[pos]);
return dp[pos][isEq];
}
ll solve(ll x,int k)
{
vector<int>digits;
while(x > 0){
digits.push_back(x%10);
x/=10;
}
reverse(digits.begin(),digits.end());
memset(dp,-1,sizeof dp);
return do_dp(digits,k);
}
int main()
{
ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
ll t,l,r,k;
cin>>t;
while(t--)
{
cin>>l>>r>>k;
cout<<solve(r,k) - solve(l-1,k)<<"\n";
}
}