首页 > 其他分享 >数位DP

数位DP

时间:2023-04-15 12:02:05浏览次数:48  
标签:node typedef int ll len DP 数位

数位DP

数位是指把一个数字按照个、十、百、千等等一位一位地拆开,关注它每一位上的数字。如果拆的是十进制数,那么每一位数字都是 0~9,其他进制可类比十进制。

数位 DP:用来解决一类特定问题,这种问题比较好辨认,一般具有这几个特征:

  1. 要求统计满足一定条件的数的数量(即,最终目的为计数);
  2. 这些条件经过转化后可以使用「数位」的思想去理解和判断;
  3. 输入会提供一个数字区间(有时也只提供上界)来作为统计的限制;
  4. 上界很大(比如 10^{18}),暴力枚举验证会超时。

例题

不要62

https://loj.ac/p/10167

#include<bits/stdc++.h>
using namespace std;
int n,m,a[100],f[100][3];
int sc(int len,int t,int ff)
{
	int end,i;
	if (len==0)
		return 1;
	if ((ff)and(f[len][t]!=-1))
		return f[len][t];
	ff==false?end=a[len]:end=9;
	int s=0;
	for (i=0;i<=end;i++)
	{
		if (i==4) continue;
		if (i==6)
			s=s+sc(len-1,1,ff or i<a[len]);
		else
			if (!((i==2)and(t==1)))
				s=s+sc(len-1,0,ff or i<a[len]);
	}
	if (ff)
		f[len][t]=s;
	return s;
}
int solve(int x)
{
	int len=0;
	while (x>0)
	{
		a[++len]=x%10;
		x=x/10;
	}
	memset(f,-1,sizeof(f));
	return sc(len,0,0);
}
int main()
{
	while (cin>>n>>m)
	{
		if ((n==0)and(m==0))
			break;
		cout<<solve(m)-solve(n-1)<<endl;
	}
}

数字计数

统计n到m中所有数位出现的次数

https://loj.ac/p/10169

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll n,m,i,g[20],c[20],f[100][2][20],a[100];
ll ff[20];
void build()
{
	ll x=1;
	for (int i=0;i<=12;i++)
	{
		ff[i]=x;
		x=x*10;
	}
}
void sc(int len,int t,int w,ll x)
{
	if (len==0)
		return;
	if (t and(f[len][w][0]!=-1))
	{
		for (int i=0;i<=9;i++)
			g[i]=g[i]+f[len][w][i];
		return;
	}
	int end,i;ll s=0;
	t==0?end=a[len]:end=9;
	ll b[10];
	for (i=0;i<=9;i++)
		b[i]=g[i];
	for (i=0;i<=end;i++)
	{
		sc(len-1,t or i<a[len],w or i>0,x);
		if (!((w==0)and(i==0))or(len==1))
		{
			if (t or i<a[len])
				g[i]=g[i]+ff[len-1];
			else g[i]=g[i]+x%ff[len-1]+1;
		}
	}
	if (t)
		for (i=0;i<=9;i++)
			f[len][w][i]=g[i]-b[i];
}
void solve(ll x)
{
	ll len=0,y=x;
	while (x>0)
	{
		a[++len]=x%10;
		x=x/10;
	}
	memset(g,0,sizeof(g));
	if (len==0) g[0]=1;
	else sc(len,0,0,y);
}
int main()
{
	cin>>n>>m;
	build();
	memset(f,-1,sizeof(f));
	solve(m);
	for (i=0;i<=9;i++)
		c[i]=g[i];
	solve(n-1);
	for (i=0;i<=8;i++)
		cout<<c[i]-g[i]<<' ';
	cout<<c[9]-g[9]<<endl;
}

恨7不是妻

https://vjudge.net/problem/LibreOJ-10168

题解:https://www.cnblogs.com/graytido/p/12202754.html

#include <bits/stdc++.h>
using namespace std;
/*    freopen("k.in", "r", stdin);
    freopen("k.out", "w", stdout); */
//clock_t c1 = clock();
//std::cerr << "Time:" << clock() - c1 <<"ms" << std::endl;
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#define de(a) cout << #a << " = " << a << endl
#define rep(i, a, n) for (int i = a; i <= n; i++)
#define per(i, a, n) for (int i = n; i >= a; i--)
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> PII;
typedef pair<double, double> PDD;
typedef vector<int, int> VII;
#define inf 0x3f3f3f3f
const ll INF = 0x3f3f3f3f3f3f3f3f;
const ll MAXN = 1e6 + 7;
const ll MAXM = 1e6 + 7;
const ll MOD = 1e9 + 7;
const double eps = 1e-6;
const double pi = acos(-1.0);
int a[105];
/*   1、整数中某一位是7;
  2、整数的每一位加起来的和是7的整数倍;
  3、这个整数是7的整数倍; */
struct node
{
    ll sum;   //与7无关的数的个数
    ll qsum;  //与7无关的数和
    ll sqsum; //ans
    node(ll _sum = -1, ll _qsum = 0, ll _sqsum = 0) { sum = _sum, qsum = _qsum, sqsum = _sqsum; }
};
node dp[30][15][15];
ll c[20];
node dfs(int pos, int sta1, int sta2, bool lim) //sta1各位数和%7 sta2前面%7
{
    if (pos < 0)
        return node(sta1 && sta2, 0, 0);
    if (!lim && dp[pos][sta1][sta2].sum != -1)
        return dp[pos][sta1][sta2];
    int up = lim ? a[pos] : 9;
    node ret = node(0, 0, 0);
    for (int i = 0; i <= up; i++)
    {
        if (i != 7)
        {
            node t = dfs(pos - 1, (sta1 + i) % 7, (sta2 * 10 + i) % 7, lim && i == a[pos]);
            ret.sum += t.sum;
            ret.sum %= MOD;
            ret.qsum += (((c[pos] * i % MOD) * t.sum % MOD) + t.qsum) % MOD;
            ret.qsum %= MOD;
            ret.sqsum += t.sqsum % MOD;
            ret.sqsum %= MOD;
            ret.sqsum += ((i * i * c[pos] % MOD) * c[pos] % MOD) * t.sum % MOD;
            ret.sqsum %= MOD;
            ret.sqsum += ((i * 2 * c[pos] % MOD) * t.qsum) % MOD;
            ret.sqsum %= MOD;
        }
    }
    if (!lim)
        dp[pos][sta1][sta2] = ret;
    return ret;
}
ll solve(ll x)
{
    int pos = -1;
    while (x)
    {
        a[++pos] = x % 10;
        x /= 10;
    }
    return dfs(pos, 0, 0, true).sqsum;
}
void init()
{
    c[0] = 1;
    for (int i = 1; i < 20; i++)
        c[i] = (c[i - 1] * 10) % MOD;
}

int main()
{
    int t;
    init();
    scanf("%d", &t);
    while (t--)
    {
        ll L, R;
        scanf("%lld%lld", &L, &R);
        printf("%lld\n", ((solve(R) - solve(L - 1)) % MOD + MOD) % MOD);
    }
    return 0;
}

标签:node,typedef,int,ll,len,DP,数位
From: https://www.cnblogs.com/ShadowAA/p/17320825.html

相关文章

  • DP优化
    DP优化单调队列优化WatchingFireworksisFunCF372C#include<bits/stdc++.h>usingnamespacestd;typedeflonglongll;lln,m,d,i,j,k,l,r,ma,f[2][150005],g[150005],a[305],b[305],c[305];intmain(){ cin>>n>>m>>d; for(i=1;i<=m;i++) ......
  • 线性DP
    线性DP最长公共子序列O(n*m)写法inta[MAXN],b[MAXM],f[MAXN][MAXM];intdp(){for(inti=1;i<=n;i++)for(intj=1;j<=m;j++)if(a[i]==b[j])f[i][j]=f[i-1][j-1]+1;elsef[i][j]=std::max(f[i-1][j],......
  • 背包DP
    背包DP二进制分组优化考虑优化。我们仍考虑把多重背包转化成0-1背包模型来求解。预处理物品数量是2的次方。且要覆盖物品数量的点。即2n次方+1到kindex=0;for(inti=1;i<=m;i++){intc=1,p,h,k;cin>>p>>h>>k;while(k>c){k-=c;......
  • PyQt5 软件在 macOS HiDPI 模式下出现字体模糊的问题
    ​ Retina屏幕是苹果公司在2010年在 WWDC上发布的一种高密度像素的屏幕。HiDPI是一种渲染技术,它可以让Retina屏幕上的图像更加清晰。HiDPI技术会将图像渲染成两倍于原始分辨率的大小,然后再将其缩小到原始分辨率的大小,这样就可以让图像更加清晰。PyQt5编写的软件在Wi......
  • 计算机网络 传输层协议TCP和UDP
    目录一、传输层协议二、tcp协议介绍三、tcp报文格式四、tcp三次握手五、tcp四次挥手六、udp协议介绍七、常见协议和端口八、有限状态机  一、传输层协议传输层协议主要是TCP和UDP协议主要作用1.分段和重组2.会话多路复用 二、tcp协议......
  • 调整数组顺序使奇数位于偶数前面
    输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有奇数在数组的前半部分,所有偶数在数组的后半部分。示例:输入:nums= [1,2,3,4]输出:[1,3,2,4]注:[3,1,2,4]也是正确的答案之一。提示:0<=nums.length<=500000<=nums[i]<=10000int*exchange(int*nums,......
  • 神策数据入选 IDC 中国客户数据平台 CDP 市场规模及厂商份额报告
    近日,IDC首发中国客户数据平台CDP市场规模及厂商份额报告,明确了CDP产品的功能和使用方式,以便减少购买者的困惑。IDC市场份额报告调研的厂商包括神策数据在内的15家企业,报告显示,市场前5家公司营业额几乎占整个市场的二分之一(47.1%)。报告中,IDC将CDP产品的主要功能分为......
  • 解决 dpkg 安装出错后的 Sub-process /usr/bin/dpkg returned an error code (1) 错误
    在使用dpkg-i安装.deb软件包的过程中,会出现安装失败的可能。之后无论用sudoaptinstall-forsudaptautoremove等常见的修复命令都是无效的。网络上很多解决方案都直接给出需要运行的命令,不分析原因也不说明理由。我从来不尝试这样的解决方案,除非我自己知道或是只能死马......
  • 【DP】【分治】LeetCode 53. 最大子数组和
    题目链接[https://leetcode.cn/problems/maximum-subarray/description/](53.最大子数组和"https://leetcode.cn/problems/maximum-subarray/description/")思路分析动态规划题目的时候只需要考虑最后一个阶段,因为所有的阶段转化都是相同的,考虑最后一个阶段容易发现规律在数......
  • Codeforces Round #286 (Div. 2) C题 Mr. Kitayuta, the Treasure Hunter (DFS+记忆化D
    题目地址:http://codeforces.com/contest/505/problem/C从d点开始,每个点都有三个方向,形成了一棵树,那么就从跟结点开始进行dfs查找,dp数组记录当前的点和长度,当这两个条件相同的时候,显然,后面的子树是完全相同的,于是用记忆化来优化。代码如下:#include<iostream>#include<string.h>#......