zoukankan      html  css  js  c++  java
  • 【ARC075F】Mirrored 搜索/数位dp

    Description

    ​ 给定正整数DD,求有多少个正整数NN,满足rev(N)=N+Drev(N)=N+D,其中rev(N)rev(N)表示将NN的十进制表示翻转来读得到的数

    Input

    ​ 一个正整数DD

    Output

    ​ 满足上述条件的正整数的个数

    Sample Input

    Case 1:
    63
    
    Case 2:
    75
    
    Case 3:
    864197532
    

    Sample Output

    Case 1:
    2
    
    Case 2:
    0
    
    Case 3:
    1920
    

    HINT

    ​ 1≤D≤1091≤D≤109

    ​ 样例1解释:81=18+63,92=29+63

    Sol

    我们把题目转化成rev(n)-n=d,然后折半搜索,只搜一半,另一半可以直接计算,这样的复杂度为(O(2^{18}))左右。

    然而还是有更强的做法的,这个不用搜。。可以dp。。而且复杂度只有(O(d^2*10)),具体地,在这里:orzDTZ,写得非常详细。

    Code

    搜索:

    #include <bits/stdc++.h>
    #define ll long long
    using namespace std;
    int D,cnt[19],ans;ll b[20];
    void dfs(int x,ll res,int L,int now)
    {
        if(x>(L>>1)-1){if(res==D) ans+=now*(L&1?10:1);return;}
        ll i=-9ll;while(i<9ll&&res+(i+1ll)*(b[L-x-1]-b[x])<=D) ++i;
        dfs(x+1,res+i*(b[L-x-1]-b[x]),L,now*(x==0&&i>=0?cnt[i+9]-1:cnt[i+9]));
        if(++i<=9) dfs(x+1,res+i*(b[L-x-1]-b[x]),L,now*(x==0&&i>=0?cnt[i+9]-1:cnt[i+9]));
    }
    int main()
    {
        scanf("%d",&D);
        b[0]=1ll;for(int i=1;i<19;++i) b[i]=b[i-1]*10ll;
        for(int i=0;i<=9;++i) for(int j=0;j<=9;++j) ++cnt[i-j+9];
        for(int i=1;i<=18;++i) dfs(0,0,i,1);
        printf("%d",ans);
    }
    

    dp:

    #include <bits/stdc++.h>
    using namespace std;
    int d[10005],f[10005][2][2],L,ans,lim,P=1e9+7;char D[10005];
    int dp(int n)
    {
    	int m=n>>1,res=0;
    	for(int i=0;i<=m;i++) for(int j=0;j<2;j++) for(int k=0;k<2;k++) f[i][j][k]=0;
    	f[0][0][0]=1;
    	for(int i=0;i<m;i++) for(int j=0;j<2;j++) for(int k=0;k<2;k++) if(f[i][j][k]) for(int x=0,y,j1,k1;x<10;x++)
    	{
    		k1=x+d[i+1]+k,y=k1%10,k1/=10,j1=10*j+x-y-d[n-i];
    		if(j1<0||j1>1||(!i&&(!x||!y))) continue;
    		(f[i+1][j1][k1]+=f[i][j][k])%=P;
    	}
    	if(n&1) for(int j=0,mid=(n+1)>>1;j<2;j++) for(int k=0;k<2;k++) if(f[m][j][k]) for(int x=0,y;x<10;x++)
    	{
    		y=x+d[mid]+k;
    		if((x==y%10)&&(y/10==j)) (res+=f[m][j][k])%=P;
    	}
    	if(!(n&1)) for(int j=0;j<2;j++) (res+=f[m][j][j])%=P;
    	return res;
    }
    int main()
    {
    	scanf("%s",D+1);L=strlen(D+1);lim=L<<1;
    	for(int i=1;i<=L;i++) d[L-i+1]=D[i]-'0';
    	for(int i=max(2,L);i<=lim;i++) (ans+=dp(i))%=P;
    	printf("%d
    ",(ans+P)%P);
    }
    
  • 相关阅读:
    MyISAM和InnoDB的区别
    MySQL——索引与优化
    jquery选择器及效率问题
    Mac 可设置环境变量的位置、查看和添加PATH环境变量
    javascript默认中文(汉字/标点)长度均为1的解决
    苹果下抓屏截屏方法 包括全屏、选择区域、窗口抓屏等
    java实现window phone推送通知
    设计模式总结
    NHibernate 帮助类(单例实际运用)
    访问者模式
  • 原文地址:https://www.cnblogs.com/CK6100LGEV2/p/9476170.html
Copyright © 2011-2022 走看看