P4491 [HAOI2018] 染色
根据模数猜测是 \(NTT\)。
设 \(g_i\) 表示钦定 \(i\) 种颜色有 \(S\) 个,其它不管的方案数,有 \(g_i=C_m^i\frac{n!}{(S!)^i(n-iS)!}(m-i)^{n-iS}\),设 \(f_i\) 表示恰好 \(i\) 种颜色有 \(S\) 个,有 \(g_i=\sum_{j=i}^{m}C_j^if_j\)。
根据二项式反演,有 \(f_i=\sum_{j=i}^{\min(n/S,m)}(-1)^{j-i}C_j^ig_j\),把组合数拆开,变成
\[\begin{array}{lr}
f_i=\sum_{j=i}^{\min(n/S,m)}\frac{j!}{i!(j-i)!}(-1)^{j-i}g_j\\
f_i=\frac1{i!}\sum_{j=i}^{\min(n/S,m)}(j!g_j)\cdot\frac{(-1)^{j-i}}{(j-i)!}
\end{array}
\]
用 \(NTT\) 优化一下即可。
/*
Luogu P3342 [ZJOI2014] 璀灿光华
2026-03-24
*/
#include<bits/stdc++.h>
using namespace std;
namespace IO{
template<typename T>
inline void read(T&x){
x=0;char c=getchar();bool f=0;
while(!isdigit(c)) c=='-'?f=1:0,c=getchar();
while(isdigit(c)) x=x*10+c-'0',c=getchar();
f?x=-x:0;
}
template<typename T>
inline void write(T x){
if(x==0){putchar('0');return ;}
x<0?x=-x,putchar('-'):0;short st[50],top=0;
while(x) st[++top]=x%10,x/=10;
while(top) putchar(st[top--]+'0');
}
inline void read(char&c){c=getchar();while(isspace(c)) c=getchar();}
inline void write(char c){putchar(c);}
inline void read(string&s){s.clear();char c;read(c);while(!isspace(c)&&~c) s+=c,c=getchar();}
inline void write(string s){for(int i=0,len=s.size();i<len;i++) putchar(s[i]);}
template<typename T>inline void write(T*x){while(*x) putchar(*(x++));}
template<typename T,typename...T2> inline void read(T&x,T2&...y){read(x),read(y...);}
template<typename T,typename...T2> inline void write(const T x,const T2...y){write(x),putchar(' '),write(y...),sizeof...(y)==1?putchar('\n'):0;}
}using namespace IO;
const int maxn=100,maxd=343010,maxlight=10,inf=0x3f3f3f3f;
int a,g[maxd],flag[maxd],dis[maxd],cnt_id,ans1=inf,ans2,used[maxd];
int hv[maxlight][10][maxn],cnt_hv[maxlight][10],cnt_fx[maxlight];
bool can[maxd];
string s;
vector<int>e[maxd];
queue<int>q;
void dfs(int u,int h=0){
if(u==cnt_id+1){ans1=min(ans1,h),ans2=max(ans2,h);return ;}
for(int i=1;i<=cnt_fx[u];i++){
int hh=h;
for(int j=1;j<=cnt_hv[u][i];j++) if(used[hv[u][i][j]]++==0) hh+=g[hv[u][i][j]];
dfs(u+1,hh);
for(int j=1;j<=cnt_hv[u][i];j++) used[hv[u][i][j]]--;
}
if(cnt_fx[u]!=6) dfs(u+1,h);
}
signed main(){
read(a);
for(int i=1;i<=a*a*a;i++){
read(g[i]);
getline(cin,s);
stringstream ss(s);
int x;
while(ss>>x) e[i].push_back(x);
}
for(int i=1;i<=a*a*a;i++){
if(g[i]) continue;
memset(dis,0x3f,sizeof(dis)),memset(flag,0,sizeof(flag)),memset(can,0,sizeof(can));
int bh=0;dis[i]=0;can[i]=1;
for(int v:e[i]){
bh++;
flag[v]=bh,dis[v]=1;
q.push(v);
}
while(!q.empty()){
int u=q.front();q.pop();
for(int v:e[u]){
if(dis[v]==dis[u]+1) can[v]=1;
if(dis[v]>dis[u]+1){
dis[v]=dis[u]+1;
flag[v]=flag[u];
q.push(v);
}
}
}
cnt_id++;
cnt_fx[cnt_id]=bh;
for(int j=1;j<=a*a*a;j++){
if(can[j]) continue;
hv[cnt_id][flag[j]][++cnt_hv[cnt_id][flag[j]]]=j;
}
}
dfs(1);
write(ans1,ans2);
return 0;
}

浙公网安备 33010602011771号