假设$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}^{lfloorfrac{k-1}{2} floor}(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到$lfloorfrac{k-1}{2} floor$依次确定$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 9sum_{j=i+1}^{lfloorfrac{k-1}{2} floor}(10^{k-j}-10^{j})$
又因为$10^{k-i}-10^{i}>9sum_{j=i+1}^{lfloorfrac{k-1}{2} floor}(10^{k-j}-10^{j})$,即当左边绝对值内已经是正数时,再增加$b_{i}$一定不合法,类似的负数时不能减少,因此$b_{i}$最多只有两种(恰好为正数或负数)
如果爆搜,对于每一个$k$都有$2^{lfloorfrac{k-1}{2} floor}$的复杂度,因此考虑确定$k$的范围:
对于$10^{k-i}-10^{i}>9sum_{j=i+1}^{lfloorfrac{k-1}{2} floor}(10^{k-j}-10^{j})$这个条件,更精确的,我们在右边再加上$10^{lceilfrac{k+1}{2} ceil}$后也是正确的,即$10^{k-i}-10^{i}>9sum_{j=i+1}^{lfloorfrac{k}{2} floor}(10^{k-j}-10^{j})+10^{lceilfrac{k+1}{2} ceil}$
接下来证明若$dle 10^{lceilfrac{k+1}{2} ceil}-10^{lfloorfrac{k-1}{2} floor}$,一定无解——
归纳$b_{i}=0$,即当确定$b_{i}$时$b_{0..i-1}=0$,此时来证明$b_{i}=0$
由于$d>0$,因此$b_{i}le 1$,同时$b_{i}$的系数最小即为$10^{lceilfrac{k+1}{2} ceil}-10^{lfloorfrac{k-1}{2} floor}$,因此$b_{i}ge -1$
而当$b_{i}=-1$时,$(10^{k-j}-10^{j})-d>9sum_{j=i+1}^{lfloorfrac{k}{2} floor}(10^{k-j}-10^{j})+10^{lceilfrac{k+1}{2} ceil}-10^{lceilfrac{k+1}{2} ceil}$(第一项$10^{lceilfrac{k+1}{2} ceil}$是更精确的比较,第二项是$d<10^{lceilfrac{k+1}{2} ceil}$),因此即不满足必要条件
当所有$b_{i}=0$时,不难得到$d=0$,即无解,因此有$kle 18$,总复杂度即为$o(18cdot 2^{9})$,可以通过
有1个细节:要求$a_{k}>0$,因此若$b_{0}ge 0$则$b_{0}$的对$a_{i}$贡献系数为$9-b_{0}$
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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 }