2020牛客暑期多校训练营(第六场)[H] Harmony Pairs

设S(x)表示十进制表示下x的每位数字之和,当S(A)>S(B)时,(A,B)表示一个和谐对。

给定N,求满足图片说明 的和谐对(A,B)的数量,答案对图片说明 取模。

题意:求1<=A<=B<=N,满足S(A)>S(B)的(A,B)个数 s是数码和。

题解:数位dp。定义dp[n][d][f0][f1],其中n表示从最高位开始,前n-1位都已经确定,正在处理第n位。

   d表示前n-1位的数值中,A-B的差值,这里要注意A-B可能为负,因此当差值为0时,应该将d设置为1000.

   f0表示前n-1位中,A是否与B相同(相同为1)

   f1表示前n-1位中,B是否与N相同(相同为1)

   令a[n]为N的第n位的值,i为当前遍历的A的第n位的值,j为当前遍历的B的第n位的值,可以得到:

   max(i)= j(f0==1)或者 9(f0==0)

   max(j)= a[n](f1==1)或者9(f1==0)

   则dp[n][d][f0][f1]=dp[n-1][d+i-j][f0&(i==j)][f1&(j==a[n])]

 1 #include<cstdio>
 2 #include<cstdlib>
 3 #include<algorithm>
 4 #include<cstring> 
 5 #include<queue>
 6 #define ll long long
 7 using namespace std;
 8 ll const mod=1e9+7;
 9 ll dp[105][2020][2][2];
10 int a[105];
11 char s[105];
12 ll dfs(int n,int d,int f0,int f1){
13   if (!n) return d>1000;
14   if (dp[n][d][f0][f1]!=-1) return dp[n][d][f0][f1];
15   int l1= f1 ? a[n]:9;
16   ll temp=0;
17   for (int j=0;j<=l1;j++)  //B
18     for (int i=0;i<=(f0?j:9);i++)  //A
19       temp=(temp+dfs(n-1,d+i-j,f0&(i==j),f1&(a[n]==j)))%mod;
20     return dp[n][d][f0][f1]=temp;
21 }
22 int main(){
23   memset(dp,-1,sizeof(dp));
24   scanf("%s",s);
25   int n=strlen(s);
26   for (int i=0;i<n;i++)
27     a[n-i]=s[i]-'0';
28   printf("%lld\n",dfs(n,1000,1,1));
29 return 0;
30 }

猜你喜欢

转载自www.cnblogs.com/ikkvix/p/13394794.html