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);
}
posted @ 2022-09-15 20:02  ycllz  阅读(28)  评论(0)    收藏  举报