1. 程式人生 > >Investigating Div-Sum Property

Investigating Div-Sum Property

連結

題解

注意到所有數字的和不會超過90,因此當K>90時直接輸出0 K90時,進行數位DP

程式碼

//ÊýλDP
#include <bits/stdc++.h>
#define maxk 100
#define maxn 15
#define cl(x) memset(x,0,sizeof(x))
#define ll long long
using namespace std;
ll N, lim[maxn], f[maxn][maxk][maxk], g[maxn][maxk][maxk], K, mi[maxn];
char a[maxn], b[maxn];
void preprocess()
{
    ll i;
    mi[1
]=1; for(i=2;i<maxn;i++)mi[i]=mi[i-1]*10; } ll dp(char *s) { ll i, j, k, x, ans=0; cl(f), cl(g), cl(lim); for(i=1;i<=10;i++)lim[i]=s[i]; f[0][0][0]=g[0][0][0]=1; for(i=0;i<=10;i++)for(j=0;j<=90;j++)for(k=0;k<K;k++) { if(f[i][j][k])f[i+1][j+lim[i+1]][(k+lim[i+1]*mi
[i+1])%K]+=f[i][j][k]; if(g[i][j][k]) for(x=0;x<=9;x++) { g[i+1][j+x][(k+x*mi[i+1])%K]+=g[i][j][k]; if(x<lim[i+1])f[i+1][j+x][(k+x*mi[i+1])%K]+=g[i][j][k]; } } for(i=K;i<=90;i+=K)ans+=f[10][i][0]; return ans; } int
main() { ll T, i, la, lb; preprocess(); scanf("%lld",&T); while(T--) { cl(a), cl(b); scanf("%s%s%lld",a+1,b+1,&K); if(K>90){printf("0\n");continue;} la=strlen(a+1), lb=strlen(b+1); reverse(a+1,a+la+1); reverse(b+1,b+lb+1); for(i=1;i<=la;i++)a[i]-=48; for(i=1;i<=lb;i++)b[i]-=48; a[1]--; for(i=1;i<=strlen(a+1);i++)if(a[i]<0)a[i]+=10, a[i+1]--; printf("%lld\n",dp(b)-dp(a)); } return 0; }