G. D-Function

纯粹的發表於2024-06-13

原題連結

題解

先不考慮k的限制,而是考慮對於任意一個數,存不存在一個k使得題目所給等式成立
\(n·k\) 沒有進位時,等式一定成立
(賽時也許想到這就夠了)
假如有進位呢?

對於任何一個位數大於1的數,必有 \(D(n) \lt n\) (想想十進位制是怎麼表示數的)
而對於位數為1的數,有 \(D(n)=n\)
所以只要有一個進位,就相當於一個位數為1的數變成位數大於1的數,則 \(D(kn)\) 一定小於 \(k·D(n)\)

實施

求出最大的乘上k不會進位的數 \(m\)
然後求出 \([0,l]\)\([0,r]\) 內的有多少數,其所有位上的數不大於 \(m\)
之所以這麼求是為了抵消字首0的干擾

code

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const ll mod=1e9+7;

inline void read(ll &x) {  
	x = 0;
	ll flag = 1;
	char c = getchar();
    while(c < '0' || c > '9'){
        if(c == '-')flag = -1;
        c = getchar();
    }
	while(c >= '0' && c <= '9') {
		x = (x << 3) + (x << 1) + (c ^ 48); 
		c = getchar();
	}
	x *= flag;
}

inline void write(ll x)
{
    if(x < 0){
    	putchar('-');
		x = -x;
	}
    if(x > 9) 
		write(x / 10);
    putchar(x % 10 + '0');
}

ll qpow(ll base, ll p) {
    ll res = 1, tem = base;
    while (p) {
        if (p & 1) res = (1LL * res * tem) % mod;
        p >>= 1;
        tem = (1LL * tem * tem) % mod;
    }
    return res;
}

int main() {
    ll t;
    read(t);
    while (t--) {
        ll l, r, k;
        read(l); read(r); read(k);

        ll m = 9 / k;
        ll res = (qpow(m + 1, r) - qpow(m + 1, l) + mod) % mod;
        write(res);
        putchar('\n');
    }
    return 0;
}