【AtCoder Regular Contest 075 F】Mirrored

思维题。

题目大意:

给定 $D$,定义 $\mathrm{rev}(N)$ 为将 $N$ 翻转后去掉前导 $0$ 后得到的数。

求有多少个 $N$ 满足 $\mathrm{rev}(N)=N+D$。

题解:

以四位数为例。

我们设 $N=1000a+100b+10c+d$,则 $\mathrm{rev}(N)=1000d+100c+10b+a$。

也就是说,$D=1000(d-a)+100(c-b)+10(b-c)+(a-d)=999(d-a)+90(c-b)$。

显然 $D$ 必须是 $9$ 的倍数。那么:

由于 $a,b,c,d\in[0,9]$ 且是整数,所以 $d-a,c-b\in[0,9]$。

那么唯一能影响到个位的只有 $111(d-a)$,所以 $d-a$ 的值是确定的,这两个位能选的方案数也是确定的。

接下来能影响到十位的只有 $10(c-b)$,同理也是唯一确定的。

其他位数的也以此类推,一位一位确定即可,最后判一下是否为 $0$ 即可。

如果位数是奇数,则中间的那位是可以任意钦定的,其方案数要乘 $10$。

Code:

#include<cstdio>
#include<cmath>
typedef long long LL;
int D;
LL ans=0;
LL solve(int len){
    LL now=0,ans=1;
    for(int l=0,r=len-1;l<r;++l,--r){
        LL dw=(LL)pow(10,l),qaq=((LL)pow(10,r)-dw)/9;
        if(now<D){
            int wg=(D-now)/dw%10;
            now+=qaq*wg;
            ans=ans*(10-wg-(l==0));
        }else{
            int wg=(now-D)/dw%10;
            now-=qaq*wg;
            ans=ans*(10-wg-(l==0));
        }
    }
    if(len&1)ans*=10;
    if(now==D)return ans;
    return 0;
}
int main(){
    scanf("%d",&D);
    if(D%9)return puts("0"),0;
    D/=9;
    for(int i=1;i<=18;++i)
    if(pow(10,i)>D)ans+=solve(i);
    printf("%lld\n",ans);
    return 0;
}