AtCoder Beginner Contest 262 D
D - I Hate Non-integer Number
我们思考这个问题可以转化为我在N个数里面拿x个数 然后sum可以整除x 这像一个什么?
没错就是背包
然后显然ai的数量太大了 我们可以用%x的余数来将一维变成N
看起来是个n3的dp (本来背包就是两维)dp[i][j][k]表示前i个数我们选j个sum余数为k的方案数
我们继续考虑转移:
当我们不选ai的时候 dp[i][j][k]+=dp[i-1][j][k]
当我们选ai的时候 dp[i][j][k]+=dp[i-1][j-1][(k+ai)% 欸没错 到这里我们就会发现问题
因为我们没有记录真正的总和所以对于变化的j而言我们已经无法转移了
那怎么办??? 我们可以考虑固定j 什么意思呢 就是我们把j这一维提出来 单独整个变量len 意思就是这个必须选len个 这样子就变成了n4但还是可以通过的
#include <bits/stdc++.h>
using namespace std;
const int N = 2e5+10;
const int M = 998244353;
const int mod = 998244353;
#define int long long
#define endl '\n'
#define all(x) (x).begin(),(x).end()
#define YES cout<<"Yes"<<endl;
#define NO cout<<"No"<<endl;
#define _ 0
#define INF 0x3f3f3f3f3f3f3f3f
#define fast ios::sync_with_stdio(false);cin.tie(nullptr);
int dp[110][110][110],n,a[110];
void solve() {
cin>>n;
for(int i=1;i<=n;i++)cin>>a[i];
int res=0;
for(int len=1;len<=n;len++){
memset(dp,0,sizeof dp);
dp[0][0][0]=1;
for(int i=1;i<=n;i++){
for(int j=0;j<=len;j++){
for(int k=0;k<len;k++){
dp[i][j][k]+=dp[i-1][j][k];
if(j>=1)(dp[i][j][(k+a[i])%len]+=dp[i-1][j-1][k])%=mod;
}
}
}
(res+=dp[n][len][0])%=mod;
}
cout<<res<<endl;
}
signed main(){
fast
int T;T=1;
while(T--) {
solve();
}
return ~~(0^_^0);
}