数位dp-

发布于:2025-02-24 ⋅ 阅读:(119) ⋅ 点赞:(0)

P4999 烦人的数学作业 - 洛谷

#include <bits/stdc++.h>		

#define fi first
#define se second
#define endl '\n'
#define pb push_back

using namespace std;
using LL = long long;
typedef pair<int,int> PII;
typedef pair<LL,LL> PLL;
const LL inf = 0x3f3f3f3f3f3f3f3f;
const int INF = 0x3f3f3f3f;

const int mod = 1e9 + 7;


const int N = 1e5 + 10,T = 20;


LL l,r;
LL a[23];
LL dp[23][N];//到第i位,所有数的数位和

LL mo(LL x)
{
	return (x % mod + mod) % mod;
}

LL dfs(int pos,bool limit,LL sum)
{
	if (pos == 0) return sum;
	
	if (!limit && dp[pos][sum] != -1) return dp[pos][sum];
	
	int up = limit ? a[pos] : 9;
	LL res = 0;
	for (int i = 0;i <= up;i ++)//枚举第pos位选择的数i
	{
		res = (res + dfs(pos - 1,limit && (i == up),sum + i)) % mod;
	}
	
	if (!limit) dp[pos][sum] = res;
	return res;
	
}

LL f(LL x)
{
	int len = 0;
	while(x)
	{
		a[++ len] = x % 10;
		x /= 10;
	}
	
	return dfs(len,true,0);
}

void solve()
{
	
	cin >> l >> r;
	cout << mo(f(r) - f(l - 1)) << endl;//可能出现负数
}

int main()
{
	ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
	int _ = 1;
	cin >> _;
	memset(dp,-1,sizeof dp);//可复用的,多组样例都可使用
	while(_--) solve();
	
	return 0;
}	

P2602 [ZJOI2010] 数字计数 - 洛谷

#include <bits/stdc++.h>		

#define fi first
#define se second
#define endl '\n'
#define pb push_back

using namespace std;
using LL = long long;
typedef pair<int,int> PII;
typedef pair<LL,LL> PLL;
const LL inf = 0x3f3f3f3f3f3f3f3f;
const int INF = 0x3f3f3f3f;

const int mod = 1e9 + 7;


const int N = 1e5 + 10,T = 20;

LL l,r;
LL a[15];
LL dp[15][N];

LL dfs(int pos,bool limit,bool lead,int query,int cnt)
{
	if (pos == 0) return cnt;
	
	if (!limit && !lead && ~dp[pos][cnt]) return dp[pos][cnt];
	
	int up = limit ? a[pos] : 9;
	LL res = 0;
	for (int i = 0;i <= up;i ++)
	{
		if (i == 0 && lead)	
			res += dfs(pos - 1,limit && (i == up),true,query,cnt);
		else res += dfs(pos - 1,limit && (i == up),false,query,cnt + (query == i ? 1 : 0));
	}
	
	if (!limit && !lead) dp[pos][cnt] = res;
	
	return res;
}


LL f(LL x,int query)
{
	int len = 0;
	while(x)
	{
		a[++ len] = x % 10;
		x /= 10;
	}
	return dfs(len,true,true,query,0);
}

void solve()
{
	cin >> l >> r;
	for (int i = 0;i <= 9;i ++)
		cout << f(r,i) - f(l - 1,i) << " ";
}

int main()
{
	ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
	int _ = 1;
	// cin >> _;
	memset(dp,-1,sizeof dp);//可复用的,多组样例都可使用
	while(_--) solve();
	
	return 0;
}	

1.谁是帕鲁?【算法赛】 - 蓝桥云课

#include <bits/stdc++.h>		

#define fi first
#define se second
#define endl '\n'
#define pb push_back

using namespace std;
using LL = long long;
typedef pair<int,int> PII;
typedef pair<LL,LL> PLL;
const LL inf = 0x3f3f3f3f3f3f3f3f;
const int INF = 0x3f3f3f3f;

const int mod = 1e9 + 7;


const int N = 1e5 + 10,T = 20;

LL l,r,k;
LL dp[15][N];//到第i位且没有限制,有j个封闭图形的数量
LL a[15];
int b[] = {1,0,0,0,1,0,1,0,2,1};

LL dfs(int pos,bool lim,bool lead,LL cnt)
{
	if(pos == 0)
	{
		if (cnt == k) return 1;//满足恰好有k个封闭图形
		else return 0;
	}
	
	if (!lim && !lead && ~dp[pos][cnt]) return dp[pos][cnt]; 
	
	int up = lim?a[pos]:9;
	LL res = 0;
	for (int i = 0;i <= up;i ++)
	{
		if (i == 0 && lead) 
			res += dfs(pos - 1,lim && i == up,true,cnt);
		else 
			res += dfs(pos - 1,lim && i == up, false,cnt + b[i]);
	}
	
	if (!lim && !lead) dp[pos][cnt] = res;
	
	return res;
	
}

LL f(LL x)
{
	int len = 0;
	while(x)
	{
		a[++ len] = x % 10;
		x /= 10;
	}
	return dfs(len,true,true,0);
}

void solve()
{
	cin >> l >> r >> k;
	cout << f(r) - f(l - 1) << endl;
}

int main()
{
	ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
	int _ = 1;
	// cin >> _;
	memset(dp,-1,sizeof dp);//可复用的,多组样例都可使用
	while(_--) solve();
	
	return 0;
}	

 JB国


网站公告

今日签到

点亮在社区的每一天
去签到