假设$n=\sum_{i=0}^{k}a_{i}10^{i}$(其中$a_{k}>0$),则有$d=f(n)-n=\sum_{i=0}^{k}(10^{k-i}-10^{i})a_{i}$,考虑$i$和$k-i$,不难化简得到$d=\sum_{i=0}^{\lfloor\frac{k-1}{2}\rfloor}(10^{k-i}-10^{i})(a_{i}-a_{k-i})$
(这里忽略了当$k$为偶数时$a_{\frac{k}{2}}$,因为其系数为0,因此当$k$为偶数时答案可以再乘10)
记$b_{i}=a_{i}-a_{k-i}$后,考虑去统计$b_{i}$,之后再加上对应的$a_{i}$,即$\prod(10-|b_{i}|)$种
从0到$\lfloor\frac{k-1}{2}\rfloor$依次确定$b_{i}$,当要确定$b_{i}$时(即$b_{0..i-1}$都已经确定),考虑$b_{i}$之后的位置所能产生的贡献,不难得到$b_{i}$合法的必要条件为$|d-\sum_{j=0}^{i}(10^{k-j}-10^{j})b_{j}|\le 9\sum_{j=i+1}^{\lfloor\frac{k-1}{2}\rfloor}(10^{k-j}-10^{j})$
又因为$10^{k-i}-10^{i}>9\sum_{j=i+1}^{\lfloor\frac{k-1}{2}\rfloor}(10^{k-j}-10^{j})$,即当左边绝对值内已经是正数时,再增加$b_{i}$一定不合法,类似的负数时不能减少,因此$b_{i}$最多只有两种(恰好为正数或负数)
如果爆搜,对于每一个$k$都有$2^{\lfloor\frac{k-1}{2}\rfloor}$的复杂度,因此考虑确定$k$的范围:
对于$10^{k-i}-10^{i}>9\sum_{j=i+1}^{\lfloor\frac{k-1}{2}\rfloor}(10^{k-j}-10^{j})$这个条件,更精确的,我们在右边再加上$10^{\lceil\frac{k+1}{2}\rceil}$后也是正确的,即$10^{k-i}-10^{i}>9\sum_{j=i+1}^{\lfloor\frac{k}{2}\rfloor}(10^{k-j}-10^{j})+10^{\lceil\frac{k+1}{2}\rceil}$
接下来证明若$d\le 10^{\lceil\frac{k+1}{2}\rceil}-10^{\lfloor\frac{k-1}{2}\rfloor}$,一定无解——
归纳$b_{i}=0$,即当确定$b_{i}$时$b_{0..i-1}=0$,此时来证明$b_{i}=0$
由于$d>0$,因此$b_{i}\le 1$,同时$b_{i}$的系数最小即为$10^{\lceil\frac{k+1}{2}\rceil}-10^{\lfloor\frac{k-1}{2}\rfloor}$,因此$b_{i}\ge -1$
而当$b_{i}=-1$时,$(10^{k-j}-10^{j})-d>9\sum_{j=i+1}^{\lfloor\frac{k}{2}\rfloor}(10^{k-j}-10^{j})+10^{\lceil\frac{k+1}{2}\rceil}-10^{\lceil\frac{k+1}{2}\rceil}$(第一项$10^{\lceil\frac{k+1}{2}\rceil}$是更精确的比较,第二项是$d<10^{\lceil\frac{k+1}{2}\rceil}$),因此即不满足必要条件
当所有$b_{i}=0$时,不难得到$d=0$,即无解,因此有$k\le 18$,总复杂度即为$o(18\cdot 2^{9})$,可以通过
有1个细节:要求$a_{k}>0$,因此若$b_{0}\ge 0$则$b_{0}$的对$a_{i}$贡献系数为$9-b_{0}$
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define N 21 4 #define ll long long 5 ll n,sum,ans,mi[N]; 6 void dfs(int k,int t,ll n,ll tot){ 7 if (k>(t-1)/2){ 8 if (!n)sum+=tot; 9 return; 10 } 11 ll s=mi[t-k]-mi[k]; 12 n+=9*s; 13 for(int i=-9;i<=9;i++){ 14 if (abs(n)<s)dfs(k+1,t,n,tot*(10-abs(i)-((!k)&&(i>=0)))); 15 n-=s; 16 } 17 } 18 int main(){ 19 scanf("%lld",&n); 20 mi[0]=1; 21 for(int i=1;i<=18;i++)mi[i]=mi[i-1]*10; 22 for(int i=1;i<=18;i++){ 23 sum=0; 24 dfs(0,i,n,1); 25 if (i%2==0)sum*=10; 26 ans+=sum; 27 } 28 printf("%lld",ans); 29 }