windy数(数位dp)

匿名 (未验证) 提交于 2019-12-03 00:42:01

传送门

 #include<stdio.h> #include<string.h> #include<math.h> #include<stdlib.h> #define maxn 20 long long dp[20][10];//dp[i][j]表示前面一个数为j的i位数的方案数 int bit[20]; long long dfs(int pos,int pre,int f,int lim) //pos当前枚举到的位置,pre记录pos位置前一个位置的数,因为当枚举到pos然后无前导0的时候要拿判断i和前一个数即pre的差是否>=2,如果f为1,即枚举第pos位数时有前导0,此时pre是无意义的。 {     int newf,i;//newf用来记录枚举pos-1位置时有没有前导0     int up=lim?bit[pos]:9;     if(pos==0) return 1;     if(!lim&&(f==0)&&(dp[pos][pre]!=-1)) return dp[pos][pre];     long long ans=0;      for(i=0;i<=up;i++)     {          if(f==1&&i==0)             newf=1;         else             if(f!=1)                 newf=0;             else                 if(f==1&&i!=0)                     newf=0;          if(f==1)//有前导0的话,pre无效,pow位置的数可以在0~up随便取         {              ans+=dfs(pos-1,i,newf,lim&&(i==up));         }         else         {             if(abs(pre-i)>=2)                 ans+=dfs(pos-1,i,newf,lim&&(i==up));         }      }     if(!lim&&f==0) dp[pos][pre]=ans;如果是在无限制且无前导0的情况下枚举pos位数的,那么ans可以保留起来以后用     return ans;    } long long solve(long long n) {     int cnt=0;     while(n)     {         bit[++cnt]=n%10;         n/=10;     }     return dfs(cnt,0,1,1); } int main() {     memset(dp,-1,sizeof(dp));     long long l,r;     scanf("%lld%lld",&l,&r);     printf("%lld\n",solve(r)-solve(l-1));     return 0; } 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!