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;
    	}
    }
    

  • 相关阅读:
    LeetCode 227. Basic Calculator II
    LeetCode 224. Basic Calculator
    LeetCode 103. Binary Tree Zigzag Level Order Traversal
    LeetCode 102. Binary Tree Level Order Traversal
    LeetCode 106. Construct Binary Tree from Inorder and Postorder Traversal
    LeetCode 105. Construct Binary Tree from Preorder and Inorder Traversal
    LeetCode 169. Majority Element
    LeetCode 145. Binary Tree Postorder Traversal
    LeetCode 94. Binary Tree Inorder Traversal
    LeetCode 144. Binary Tree Preorder Traversal
  • 原文地址:https://www.cnblogs.com/mountaink/p/9536724.html
Copyright © 2011-2022 走看看