[arc075f]Mirrored

前言

老感觉栋栋的程序有点迷…怎么只枚举到1e7

题目大意

给你一个数d,要你找出有多少个n,满足rev(n)=n+d,rev就是n的十进制下翻转(忽略前导零),比如“12340”翻转成“4321”.
d<=1e9

解题思路

化一下方程,rev(n)-n=d。
设ws(x)为x在十进制下的位数,s[i]表示n的第i位的数字,那么我们可以写成
i=0..ws(n)1(s[i]s[ws1i])10ws1i=d ∑ i = 0.. w s ( n ) − 1 ( s [ i ] − s [ w s − 1 − i ] ) ∗ 10 w s − 1 − i = d
那么合并一下同类项
i=0..ws(n)/21(s[i]s[ws1i])(10ws1i10i)=d ∑ i = 0.. w s ( n ) / 2 − 1 ( s [ i ] − s [ w s − 1 − i ] ) ∗ ( 10 w s − 1 − i − 10 i ) = d
挖掘一下性质。
ws(n)上界是什么?由于d非0,所以说,ws(n)的上界就是ws(d)*2。
那么我们发现其实ws(n)/2-1非常的小,考虑暴力?
设t[i]=s[i]-s[ws-1-i]。
我们只需要枚举t即可,然后统计在当前方案下有多少个对应的s。
直接搜索肯定TLE,考虑剪枝。
假如确定到t[i],令t[i]=a,无论后面怎么填,如果我的sum总比d小的话,是不可能填t[i]=a-1的。
不得了,每次只剩两个选择,时间复杂度变成 O(22log10d) O ( 2 2 ∗ l o g 10 d ) 左右。

代码

#include<cstdio> 
#include<algorithm>
#include<cstring>
#include<cmath>
#include<set>
#include<map>
using namespace std;
#define fo(i,j,k) for(i=j;i<=k;i++)
#define fd(i,j,k) for(i=j;i>=k;i--)
#define cmax(a,b) (a=(a>b)?a:b)
#define cmin(a,b) (a=(a<b)?a:b)
typedef long long ll;
const int N=2e6+5,M=1e7+50,mo=1e9+7;
ll ten[20],inc[20],ans,d,upb,i,j,cons,L,D[N],xs;
void dfs(int x,ll y,ll z)
{
    if (x>L/2-1)
    {
        if (L%2) z*=10;
        if (y==d)
            ans+=z;
        return ;
    }
    ll i=-9;
    while (i<=9&&y+i*(ten[L-x-1]-ten[x])<=d) i++;
    i--;
    D[x]=i;
    dfs(x+1,y+i*(ten[L-x-1]-ten[x]),z*(inc[i+cons]-(x==0&&i>=0)));
    i++;
    if (i>9) return ;
    D[x]=i;
    dfs(x+1,y+i*(ten[L-x-1]-ten[x]),z*(inc[i+cons]-(x==0&&i>=0)));
    //d[i]=s[i]-s[l-1-i],gx=d[i]*(10^i-10^(l-i-1)) , 
    //s[L-1]!=0, 当d>=0,存在s[L-1]=0 
}
int main()
{
    freopen("t19.in","r",stdin);
//  freopen("t19.out","w",stdout);
    scanf("%lld",&d);
    ten[0]=1;
    fo(i,1,18) ten[i]=ten[i-1]*10;
    cons=10;
    fo(i,0,9) fo(j,0,9) inc[i-j+cons]++;
    fo(upb,0,9) if (ten[upb]>d) break;
    fo(L,0,19)
        dfs(0,0,1);
    printf("%lld",ans);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值