烹饪
题意:
给定长度为
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=任意正整数
a1∗x1+a2∗x2+...+an∗xn=任意正整数 有解
等价于
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
max,bool 之类不需要
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;
}