0
点赞
收藏
分享

微信扫一扫

数论+计数dp

成义随笔 2022-02-06 阅读 74

烹饪
题意:
给定长度为 n n n 的序列,第 i i i 道菜可以增加或减少 a i a_i ai 美味值,定义最佳的挑选食材方案为:选出的 m m m 个数可以组成任意正整数的美味值
思路:
题解
这里可以用到 e x g c d exgcd exgcd,形如 a x + b y = m ax+by=m ax+by=m 的不定方程有解的充要条件为 g c d ( a , b ) ∣ m gcd(a,b)|m gcd(a,b)m
e x g c d exgcd exgcd 可以拓展到 n n n 个数
要使得 a 1 ∗ x 1 + a 2 ∗ x 2 + . . . + a n ∗ x n = 任 意 正 整 数 a_1*x_1+a_2*x_2+...+a_n*x_n=任意正整数 a1x1+a2x2+...+anxn= 有解
等价于 g c d ( a 1 , a 2 , . . . , a n ) ∣ 任 意 正 整 数 gcd(a_1,a_2,...,a_n)|任意正整数 gcd(a1,a2,...,an)
也就是 g c d gcd gcd 可以被任意正整数整除
显然 g c d = 1 gcd=1 gcd=1
至此问题转化为求 n n n 个数选出任意个数的 g c d gcd gcd 1 1 1 方案数
细节:计数dp滚动数组用完的上一层需要清空,维护 m a x , b o o l max,bool maxbool 之类不需要
code:

#include<bits/stdc++.h>
#define endl '\n'
#define ll long long
#define ull unsigned long long
#define ld long double
#define all(x) x.begin(), x.end()
#define eps 1e-6
using namespace std;
const int maxn = 3e3 + 9;
const int mod = 998244353;
const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3f;
ll n, m;
int f[2][maxn];

void work()
{
	cin >> n;
	int op = 1;
	for(int i = 1, x; i <= n; ++i, op ^= 1){
		cin >> x;
		(f[op][x] += 1) %= mod;
		for(int j = 1; j <= 2000; ++j){
			(f[op][j] += f[op^1][j]) %= mod;
			int k = __gcd(j, x);
			(f[op][k] += f[op^1][j]) %= mod;
		}
		for(int j = 1; j <= 2000; ++j) f[op^1][j] = 0;// 记得清空用完的这层
	}
	cout << f[op^1][1];
}

int main()
{
	ios::sync_with_stdio(0);
//	int TT;cin>>TT;while(TT--)
	work();
	return 0;
}

举报

相关推荐

0 条评论