• 洛谷P3413 萌数


    https://www.luogu.com.cn/problem/P3413

    回文长度2或者3就可以裁定,值得注意的是dp[pos][pre][ppre]可能应对3334321和5554321(都有321),所以要引入最新的变量才行。

    dp[pos][pre][ppre][sum],具体套了板子,返回的时候记得让pre和ppre的数字不是前导0

    #include<iostream>
    #include<queue>
    #include<string>
    #include<cstring>
    using namespace std;
    typedef long long ll;
    int T, n, m, len, a[2020];
    ll l, r, dp[1010][14][13][3];
    ll mod = 1e9 + 7;
    
    //                                  记录答案 ppre是1能算
    ll dfs(int pos, int pre, int ppre, ll sum, int d, int lead, int limit)
    //pos搜到的位置
    //pre前一位数
    //st当前公差最大差值
    //sum整个数字的最大价值
    //d共差
    //lead判断是否有前导0
    //limit判断是否有最高位限制
    {
    	if (pos > len) return sum;//dp结束
    	//记录状态(计划搜索)
    	//注意d有负数,最小可以到-9,所以记录时数组下标是d+10
    	if ((dp[pos][pre][ppre][sum] != -1 && (!limit) && (!lead)) && d == 1) return dp[pos][pre][ppre][sum] %= mod;
    	ll ret = 0;
    	int res = limit ? a[len - pos + 1] : 9;//最高位最大值
    
    	for (int i = 0; i <= res; i++)
    	{
    		//有前导0且这位也是前导0,一切不变只有位数变化
    		if ((!i) && lead) {
    			ret += dfs(pos + 1, 0, 0, 0, 0, 1, limit && (i == res));
    			ret %= mod;
    		}
    
    		//有前导0但这位不是前导0(这位是数字的最高位)开始有前一位,一个数形成等差数列
    		else if (i&&lead) {//当前位置是最高位
    			ret += dfs(pos + 1, i, 0, 0, 0, 0, limit && (i == res));
    			ret %= mod;
    		}
    		else {//前面已经有非0的数字了lead = 0
    			ll su = (i == pre)  || (sum == 1);
    			if (d == 1 && i == ppre) su = 1;
    			ret += dfs(pos + 1, i, pre, su, 1, 0, limit && (i == res));
    			ret %= mod;
    
    		}
    	}
    	ret %= mod;
    	//没有前导0和最高限制时可以直接记录当前dp值以便下次搜到同样的情况可以直接使用。
    	return (!limit && !lead && d == 1) ? dp[pos][pre][ppre][sum] = ret : ret;
    }
    int list[2020];
    
    
    ll cal(string  x,int cl)
    {
    	len = 0;
    	
    	for (int i = 0; i < x.length(); i++) {
    		list[i] = x[i] - '0';
    	}
    	list[x.length()-1] -= cl;
    
    	for (int i = x.length() - 1; i >= 0; i--) {
    		if (list[i] < 0) {
    			list[i] = 9;
    			list[i - 1] --;
    		}
    	}
    	int f = 0;
    	for (int i = 0; i < x.length(); i++) {
    		if (f == 0 && list[i] == 0) list[i] = -1;
    		if (list[i] > 0) f = 1;
    	}
    	
    	for (int i = x.length() - 1; i >= 0; i--) {
    		if (list[i] == -1) break;
    		a[++len] = list[i];
    	}
    	memset(dp, -1, sizeof dp);
    	return dfs(1, 0, 0, 0, 0, 1, 1);//-38是随便赋的其实赋成-10就行了……
    }
    
    string sn;
    
    int main()
    {
    	
    	cin >> sn;
    	ll ans = cal(sn, 1);
    	cin >> sn;
    	ll cns = cal(sn, 0); 
    	cout << (cns - ans + mod) % mod << endl;
    	//l是0的时候要特别注意!
    	//printf("%lld
    ", part(r) - part(l-1));
    	
    	return 0;
    }
    

      

    寻找真正的热爱
  • 相关阅读:
    构造函数创建对象和Object.create()实现继承
    DIV伸缩盒子box
    阿里巴巴面试题
    在字符串上添加一些方法,让字符串具有新添加方法的功能
    JQuery常用函数及功能小结--转载
    滚动公告,永远只显示一条
    JS自定义属性兼容
    手机端touchstart,touchmove,touchend事件,优化用户划入某个可以点击LI的效果
    图片预加载问题
    多联动导航
  • 原文地址:https://www.cnblogs.com/lesning/p/13646038.html
Copyright © 2020-2023  润新知