UVa 11361 Investigating Div-Sum Property (数位dp)

题目链接:https://onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=25&page=show_problem&problem=2346

唯一的问题就是 \(k\) 太大数组开不下,但发现所有位数之和最多不会超过 \(90\),也就是 \(k\) 大于 \(90\) 一定无解

#include<cstdio>
#include<cstring>
#include<vector>
using namespace std;
typedef long long ll;

const int maxn = 105;

int T, k;
ll A, B;
ll dp[maxn][maxn][maxn][2];

vector<int> dig;

ll dfs(int pos, int sum, int sel, int lim){ 
	if(pos == 0) {
		if(sum == 0 && sel == 0) return 1;
		else return 0;
	}
	if(dp[pos][sum][sel][lim] != -1) return dp[pos][sum][sel][lim];
	
	int up = lim ? dig[pos] : 9;
	ll res = 0;
	for(int i = 0 ; i <= up ; ++i){
		res += dfs(pos-1, (sum*10+i)%k, (sel+i)%k, lim & (i == up));
	}
	dp[pos][sum][sel][lim] = res;
	
	return res;
}

ll solve(ll x){
	dig.clear();
	memset(dp, -1, sizeof(dp));
	dig.push_back(-1);
	
	ll tmp = x;
	while(tmp){
		dig.push_back(tmp%10);
		tmp /= 10;
	}
	
	return dfs(dig.size()-1, 0, 0, 1);
}

int main(){
	int T;
	scanf("%d", &T); 
	for(int kase = 1 ; kase <= T ; ++kase){
		scanf("%lld%lld%d", &A, &B, &k);
		if(k > 90) printf("0\n");
		else printf("%lld\n", solve(B) - solve(A-1));
		
	}
	return 0;
}
posted @ 2021-08-15 00:44  Tartarus_li  阅读(62)  评论(0编辑  收藏  举报