HDU multi-school sixth 1011 11 Dimensions - DP + thinking

Topic links: point I ah ╭ (╯ ^ ╰) ╮

Subject to the effect:

    Length of n n number, the location is part It can be 0 0 ~ 9 9
    requires this number is divisible by m m q q times ask
    Always ask first k k small solutions

Problem-solving ideas:

    for 23 ? ? 56 ? ? 23??56??
    Be split in 23005600 23005600 + + ? ? 00 ? ? ??00??
    Then consider The program, c n t cnt question mark number of programs 1 0 c n t 10^{cnt}
    as k 1 0 18 k≤10^{18} , if 1 0 c n t 10^{cnt} number in the uniform distribution, divisible m m number of about 1 0 c n t m \frac{10^{cnt}}{m}
    therefore c n t = 20 cnt = 20 can be, that is, after explore 20 20 question mark scheme foregoing question mark taken as 0 0


     d p [ i ] [ j ] dp[i][j] is the first to i i question mark, die m m is j j program numbers
     d p [ i ] [ j ] = d p [ i 1 ] [ j + 1 0 i × x ] dp[i][j] = \sum dp[i-1][j + 10^i \times x]    x [ 0 , 9 ] x ∈ [0,9]
    Note i = 1 i=1 time, you want to add to the initial impact, that is, 23005600 23005600
    can be understood as the first to solve the initial impact, if not the most greedy with high
    time to enumerate the query from high to low, the initial impact while also taking into account the first
    time the complexity: O ( 20 m 10 + q 20 10 ) O(20*m*10 + q*20*10)

Core: DP + thinking

#include<bits/stdc++.h>
#define deb(x) cerr<<#x<<" = "<<(x)<<'\n';
using namespace std;
typedef long long ll;
const int maxn = 5e4 + 5;
const ll mod = 1e9 + 7;
int T, n, m, q;
char s[maxn];
ll dp[30][30], fac1[50], fac2[50];

int main() {
	scanf("%d", &T);
	while(T--) {
		scanf("%d%d%d%s", &n, &m, &q, s);
		ll p1 = 1, p2 = 1, val = 0, rem = 0, cnt = 0, k;
		for(int i=n-1; ~i; i--) {
			if(isdigit(s[i])) {
				val = (val + (s[i]-'0') * p1 % mod) % mod;
				rem = (rem + (s[i]-'0') * p2 % m) % m;
			} else if(cnt < 20) {
				fac1[++cnt] = p1;
				fac2[cnt] = p2;
			}
			p1 = p1 * 10 % mod;
			p2 = p2 * 10 % m;
		}
		memset(dp, 0, sizeof(dp));
		dp[0][0] = 1;
		for(int i=1; i<=cnt; i++)
			for(int j=0; j<m; j++)
				for(int x=0; x<10; x++) {
					if(i > 1) dp[i][j] += dp[i-1][(j + fac2[i] * x % m) % m];
					else dp[i][j] += dp[i-1][(j + rem + fac2[i] * x % m) % m];
					if(dp[i][j] >= 1e18 + 10 || dp[i][j] < 0) dp[i][j] = 1e18 + 10;
				}
				
		while(q--) {
			scanf("%lld", &k);
			if(dp[cnt][0] < k) {
				puts("-1");
				continue;
			}
			ll ans = val, pre_rem = 0, now_rem;
			for(int i=cnt; i; i--)
				for(int x=0; x<10; x++) {
					if(i > 1) now_rem = (pre_rem + fac2[i] * x % m) % m;
					else now_rem = (pre_rem + rem + fac2[i] * x % m) % m;
					
					if(dp[i-1][now_rem] < k) k -= dp[i-1][now_rem];
					else {
						pre_rem = now_rem;
						ans = (ans + fac1[i] * x % mod) % mod;
						break;
					}
				}
			printf("%lld\n", ans);
		}
	}
}
Published 221 original articles · won praise 220 · views 20000 +

Guess you like

Origin blog.csdn.net/Scar_Halo/article/details/103102386