zoukankan      html  css  js  c++  java
  • uva11361 特殊数的数量(数位dp)

    题目传送门

    题目大意:给你一个n-m的区间,问你这个闭区间内的特殊数有几个,特殊数的要求是 数的本身 和 各位数字之和  mod k 等于0.

    思路:刚接触数位dp,看了网上的题解,说用dp[i][j][s]表示,总共有i位,数字本身mod k为j,各位数之和mod k为s的数量,然后状态转移方程是dp[i][(j+x)%k][(s*10+x)%k]+=dp[i][j][s],第一次看这方程感觉好有道理,然后看代码发现数位dp最重要的还是计数原理,过了好久才a了这道题。主要的思路放在代码注释里了。

    #include<iostream>
    #include<algorithm>
    #include<cstdlib>
    #include<sstream>
    #include<cstring>
    #include<bitset>
    #include<cstdio>
    #include<string>
    #include<deque>
    #include<stack>
    #include<cmath>
    #include<queue>
    #include<set>
    #include<map>
    #define INF 0x3f3f3f3f
    #define CLR(x,y) memset(x,y,sizeof(x))
    #define LC(x) (x<<1)
    #define RC(x) ((x<<1)+1)
    #define MID(x,y) ((x+y)>>1)
    using namespace std;
    typedef pair<int,int> pii;
    typedef long long ll;
    const double PI=acos(-1.0);
    int fact[10]= {1,1,2,6,24,120,720,5040,40320,362880};
    const int maxn = 100005;
    ll dp[11][90][90];
    int po[11];
    void brea(ll n)
     {
    	stack<int >s;
    	while(n>0) 
    	{
    		s.push(n%10);
    		n/=10;
    	}
    	while(!s.empty())
    	 {
    		po[++po[0]]=s.top();
    		s.pop();
    	}
    	//此时po[0]存的是位数   然后其他的就是从第一位到最后一位了
    }
    ll cs(ll n,ll k) {
    	memset(dp,0,sizeof(dp));
    	memset(po,0,sizeof(po));
    	brea(n);     //把n拆开放到数组中 
    	int ans=0,ant=0;
    	for(int i=1; i<=po[0]; i++) 
    	{
    
    		for(int j=0; j<k; j++) 
    		{      //处理  0-69  因为只有十位上是0-6时  s才可以取到0和9
    			for(int m=0; m<k; m++)
    			 {
    				for(int s=0; s<=9; s++) 
    				{
    					dp[i][(j+s)%k][(m*10+s)%k]+=dp[i-1][j][m];
    				}
    			}
    		}
    		for(int j=0; j<po[i]; j++) //处理70 71 72  而73没有被计算
    		{                           
    		//由于这里是  <   所以在处理第一位的时候  7并没有被计算   所以下一次循环时 只有0-6被处理了
    			dp[i][(ans+j)%k][(ant*10+j)%k]++;
    		}
    		ans=(ans+po[i])%k;        //各位数之和mod
    		ant=(ant*10+po[i])%k;     //本身mod
    	}
    	if(ans==0&&ant==0)dp[po[0]][0][0]++;  //处理73
    	return dp[po[0]][0][0];
    }
    int main() {
    	int t;
    	cin>>t;
    	while(t--)
    	 {
    		ll n,m,k;
    		cin>>n>>m>>k;
    		if(k>90) //由于n和m最多10位  最大也就10个9   如果k为91   那就肯定不存在这样的数
    		{         
    			cout<<0<<endl;
    			continue;
    		}
    		cout<<cs(m,k)-cs(n-1,k)<<endl;
    	}
    }
    

  • 相关阅读:
    自动脚本工具新版 v2.0
    Flash 导出图片和声音
    as3 工具类分享 CookieMgr
    时间戳与时间
    OpenGL 加载位图(BMP)贴图
    as3+java+mysql(mybatis) 数据自动工具(七)
    as3+java+mysql(mybatis) 数据自动工具(六)
    as3+java+mysql(mybatis) 数据自动工具(五)
    as3+java+mysql(mybatis) 数据自动工具(四)
    将博客搬至CSDN
  • 原文地址:https://www.cnblogs.com/mountaink/p/9536724.html
Copyright © 2011-2022 走看看