【问题标题】:multiples of x in a number一个数中 x 的倍数
【发布时间】:2020-08-20 07:41:31
【问题描述】:

假设我们有一个从 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';

}

 }

谁能告诉我这个问题的更好逻辑?

【问题讨论】:

  • 1.使用动态编程,我们可以编写一个函数f(x,d),它给出了[0,x] 范围内的数字数量,这样每个数字都是d 的倍数,这样的函数的运行时间是O(log x) 2。那么答案很简单f(R,x) - f(L-1,x)
  • 如果你能给出一个失败的示例测试用例会有所帮助。
  • @Photon 你能在 l=301 r=600 和 x=3 上实现你的逻辑吗?
  • @Photon 你所说的那个函数已经在我的代码中了,我的代码中的 s1 函数也是如此。
  • @Photon 请回答。

标签: c++ algorithm numbers


【解决方案1】:
  1. 使用动态编程,我们可以编写一个函数f(x,d),它为我们提供[0,x] 范围内的数字数量,这样每个数字都是d 的倍数
  2. dp 状态:[position in X][is our number prefix == X prefix?]
  3. 将使用log10(X) * 2空格
  4. 开始状态明显是[0][1]
  5. 然后我们只需填写 dp 表,使用递归特别容易,我们只需检查我们可以添加的下一个符合所有条件的数字是什么
  6. 因此,如果我们删除常量,此类 dp 函数的总复杂度将是 O(log10(X) * 2 * 10) 或简单的 O(log N)
  7. 那么答案就是 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";
    }
}

【讨论】:

  • 为什么你使用 dp 矩阵的最后一列?
  • @sukesh 刚刚意识到它实际上不需要,编辑了答案
猜你喜欢
  • 1970-01-01
  • 2020-05-11
  • 1970-01-01
  • 2013-11-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多