分析:此题a[i],b[i],c[i]范围只有400,因此可以设一个三维数组dp[i][j][k]
dp[i][j][k]表示当一个人的IQ为i,EQ为j,AQ为k时可被dp[i][j][k]家公司录取
再考虑,如何表示被几家公司录取,即dp[i][j][k]
若采用加法,会发现公司可能会重复计算
如: 当dp[2][2][2]时可被1,2公司录取,dp[3][3][3]时可被1,2,3公司录取
采用加法 dp[4][4][4] 则会至少会重复计算2公司一次,故不可以
正确采用异或,用1<<i是否等于1表示能否被第i家公司录取
则dp[i][j][k]=dp[i][j][k] | dp[i-1][j][k] |dp[i][j-1][k] | dp[i][j][k-1]
代码:
#include<bits/stdc++.h>
#include <random>
using namespace std;
const int MXN=407;
const long long mod=998244353;
int n;
int dp[MXN][MXN][MXN];
int fun(int x){
int cnt=0;
while(x){
if(x&1)cnt++;
x>>=1;
}
return cnt;
}
long long fast(long long x,int s){
long long res=1,tmp=x;
while(s){
if(s&1) res=res*tmp%mod;
tmp=tmp*tmp%mod;
s>>=1;
}
return res;
}
int main(){
ios::sync_with_stdio(false);
int q,i,j,k,seed,m,a,b,c,sum;
long long res=0;
cin>>n>>q;
for(i=1;i<=n;i++){
cin>>m;
for(j=1;j<=m;j++){
cin>>a>>b>>c;
dp[a][b][c]|=(1<<(i-1));
}
}
for(i=1;i<MXN;i++){
for(j=1;j<MXN;j++){
for(k=1;k<MXN;k++){
dp[i][j][k]|=dp[i-1][j][k];
dp[i][j][k]|=dp[i][j-1][k];
dp[i][j][k]|=dp[i][j][k-1];
}
}
}
cin>>seed;
std::mt19937 rng(seed);
std::uniform_int_distribution<> u(1,400);
int lastans=0;
for (int i=1;i<=q;i++)
{
int IQ=(u(rng)^lastans)%400+1; // The IQ of the i-th friend
int EQ=(u(rng)^lastans)%400+1; // The EQ of the i-th friend
int AQ=(u(rng)^lastans)%400+1; // The AQ of the i-th friend
lastans=fun(dp[IQ][EQ][AQ]);// The answer to the i-th friend
res=(1ll*res+(lastans*fast(seed,q-i)%mod))%mod;
}
cout<<res<<"\n";
}