atcoder.jp/contests/ty…
#include <bits/stdc++.h>
using namespace std;
using ll=long long;
const int M=1e9+7;
const int lg=62;
int main(){
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
ll n,b,k;cin>>n>>b>>k;
vector<int>c(k);
for(auto& ci:c)cin>>ci;
auto mul=[&](const vector<ll>&dpi,const vector<ll>& dpj,ll tj)->vector<ll>{
vector <ll>res(b,0);
for(ll p=0;p<b;p++){
for(ll q=0;q<b;q++){
int nr=(p*tj+q)%b;
res[nr]=(res[nr]+dpi[p]*dpj[q])%M;
}
}return res;
};
// ten[i] = 10^(2^i) mod B
vector<ll>ten(lg,10);
for(int i=1;i<lg;i++){
// 10^(2^i) = (10^(2^(i-1)))^2
ten[i]=(ten[i-1]*ten[i-1])%b;
}vector<vector<ll>>db(lg,vector<ll>(b,0));
for(int k1=0;k1<k;k1++){
db[0][c[k1]%b]+=1;//一位的余数是本身
}for(int i=1;i<lg;i++){
db[i]=mul(db[i-1],db[i-1],ten[i-1]);
//2 位数字 = 1 位数字 + 1 位数字 拼接起来
//4 位数字 = 2 位数字 + 2 位数字 拼接起来
//8 位数字 = 4 位数字 + 4 位数字 拼接起来
}vector<ll>res(b,0);
res[0]=1;
//把 N 拆成二进制,然后用「拼接」的方式,拼出一个 N 位的数字!
for(int i=0;i<lg;i++){
if(n&(1ll<<i)){
res=mul(res,db[i],ten[i]);
}
}cout<<res[0]<<endl;
}
思路
1.dp基础:求这种问题,dp[i + 1][(r * 10 + c[k]) % B] += dp[i][r]
此时的时间复杂度是 O(NB)。直接计算一定会超时(TLE)。
2.就算用矩阵快速幂优化到 O(B3logN),在 B=1000 时依然无法通过。
3.使用倍增法后,时间复杂度可以优化到 O(B2logN)
为什么倍增
N 巨大到 1e18,根本不能一位一位递推,只能用 log 级别的方法,而倍增就是专门干这个的。