Terraced fields

*原题链接

  • 题意:要求出所有 \(1 \leqslant x\leqslant n\) 的范围内,能整除 \(8\) 的所有数的数字 \(8\)\(6\) 出现的数量。
  • 题解:神似数位 \(dp\) 要做的事情,但是因为不连续,所以没有想法。并且数据范围也暗示了是数位dp。然后赛后通过讲解,知道了, \(8\) 是以 \(1000\) 循环,然后发现 \(n\mod 1000\) 是连续的,然后大力分类讨论求解,问题的难点,在于如何把求整除 \(8\) 的数,转化成连续的数。
  • 代码:

#include <bits/stdc++.h>
#define inf 0ddddd3f3f3f3f
using namespace std;
typedef long long ll;
typedef long double ld;
const ll N = 2e5 + 94;
const ld eps = 1e-8;
const ld pi = acos(-1.0);

ll dp[222][222];
ll FORCE[N];

ll JUDGE[N];
ll cnt[10101];
ll judge(ll x) {
    ll ret = 0;
//return 1;
  //  if (JUDGE[x])return JUDGE[x];
   // ll X = x;
    while (x) {
        if (x % 10 == 6 || x % 10 == 8) ret++;
        x /= 10;
    }
    return  ret;
}

ll baoli(ll x) {
    ll ret = 0;
    for (ll i = x; i >=1 ; i--) {
        ret += judge(i);
    }
    return ret;
}
ll force(ll x) {
    ll ret = 0;
    return FORCE[x];
    for (int i = 1; i * 8 <= x; i++) {
        ll num = i * 8;
        ret += judge(num);
    }
    return ret;
}
void init() {
    for (int i = 1; i <= 10010; i ++) {
        judge(i);
    }
    for (int i = 1; i <= 10010; i ++) {
        FORCE[i] = FORCE[i-1];
        if (i%8 == 0)
        FORCE[i] += judge(i);
    }
    for (int i = 1; i <= 19; i ++) {
        ll t = 0;
        for (int j = 1; j <=9; j ++) {
            if (j == 6 || j == 8) {
                t+=(ll)pow(10, i-1) ;
            }
            dp[i][j] = dp[i][0] * (j + 1) + t;
           // cout << "len " << i << " " << j <<  ":  " << dp[i][j] << endl;
            //if (i == 8)return;
           // cout << "baoli  " << (ll)pow(10, i - 1) *  (j + 1) -1<<"  -->  " << baoli((ll)pow(10, i - 1) *  (j + 1) -1) << endl;
        }
        dp[i + 1][0] = dp[i][9]
        ;
    }
    cnt[0] = 1;
    for (int i = 1;i <= 1010;i ++) {
        cnt[i] += cnt[i-1];
        if (i % 8 ==0 )cnt[i] ++ ;
    }
}

ll DP(ll x) {
    vector<ll>nums;
    nums.push_back(1);
    ll X = x;
    ll mod = 1;
    vector<ll>Nums;
    Nums.push_back(10);
    while (x) {
        nums.push_back(x%10);
        x /= 10;
        Nums.push_back(X%mod + 1);
        mod *= 10;
    }
    ll ret = 0;
   // cout << nums[1] << " " << nums[2] << endl;
    for (int i = nums.size()-1; i >= 1; i -- ) {
       // cout << i << "!!" << endl;
        ll dig = nums[i];
        
        if (i == 1) {
            ret += dp[i][dig];
        } else if (dig == 6||dig == 8) {
            //cout << Nums[i]<<"!!!" << endl;
            ret += Nums[i];
            ret += dp[i][dig - 1];
        }
        else if(dig == 0) continue;
        else
        ret += dp[i][dig-1];
    }
    // if (ret != baoli(X)) {
    //     cout << "X  " << X << endl;while(1); 
    // }
    //cout << ret << "?" << endl;
    //cout << baoli(X) << endl;
    return ret * 125 + (X+1) * force(1000);
}
ll getans(ll n) {
    ll ans = 0;
    if (n / 1000 > 0)
        ans = DP(n / 1000 - 1) + force(n % 1000 ) +
              judge(n / 1000) * (cnt[n % 1000]) + (n % 8 == 0 ? 0 : judge(n));
    else
        ans = force(n) + (n % 8 == 0 ? 0 : judge(n));
   // cout << cnt[n%1000] << endl;
   // cout << judge(n/1000) << endl;
  // cout << DP(n/1000-1) << " " << force(n%1000) << " " << judge(n/1000) << " " << cnt[n%1000] << endl;
    return ans;
}
void solve() {
    ll n, x, y;
    cin >> n;
   // while (cin >> n) {cout << getans(n)<<endl;}
    // for (int n = 1; n <= 100000; n ++) {
    //    // DP(n);
    //    // cout << "?";
    //     if (force(n) + ((n%8 == 0) ? 0:judge(n)) == getans(n))continue;
    //     else {
    //         cout << n << endl;
    //         cout << "Baoli(n)" << force(n) + ((n % 8 == 0) ? 0 : judge(n))
    //              << endl;
    //         cout << "getans" << getans(n) << endl;
    //         cout << force(n-1) << endl;
    //         cout << getans(n-1) << endl;
    //         while (1);
    //     }
    // }
    cout << getans(n) << "\n";
}
int main() {
    ll n = 1;
    init();
    ios::sync_with_stdio(0);
    while (cin >> n) {
        while (n--) {
            solve();
        }
    }
    return 0;
}
posted @ 2021-06-13 09:46  u_yan  阅读(58)  评论(0编辑  收藏  举报