修仙录 3.25
作者:互联网
怎么每道题都跟我没学过的公式有关。。
可惜没想出T1dp50分(改是改了)
改不动的,该前面的好了。
jzoj 6079 染色问题
https://jzoj.net/senior/#main/show/6079
想法清奇。
神奇。
主要讲讲最后状压dp的部分
f[i][s]:用i种颜色染s集合的方案数
转移显然,多用一种颜色,就枚举这个颜色的集合,与已经染好的构成新集合
同颜色集合权值预处理,不同颜色随dp转移就好
因为是选i种颜色,最后乘上一个Cki
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<vector>
#include<queue>
#define LL long long
using namespace std;
const int MAXN=1e5+5;
const int mod=1e9+7;
int n,m,k,tot,id[MAXN],t[MAXN];
int head[MAXN],du[MAXN],cnt;
struct edge{
int to,next;
LL a,b;
edge(){to=next=a=b=0;}
edge(int to,int next,LL a,LL b):to(to),next(next),a(a),b(b){}
};
vector<edge>e,g[15];
queue<int>q;
bool isv[MAXN];
LL ans=1,val[1<<15],sum,f[15][1<<15],ml[MAXN],inv[MAXN];
void add(int u,int v,int a,int b){
e.push_back(edge(v,head[u],a,b)),du[v]++,head[u]=++cnt;
e.push_back(edge(u,head[v],a,b)),du[u]++,head[v]=++cnt;
}
void del_1(){
for(int i=1;i<=n;i++) if(du[i]==1) q.push(i),isv[i]=1;
while(!q.empty()){
int x=q.front();q.pop();
if(du[x]==1) ans=ans*(k-1)%mod;
for(int i=head[x];i;i=e[i].next){
int y=e[i].to;
if(--du[y]==1) q.push(y),isv[y]=1;
}
}
}
void del_2(){
for(int x=1;x<=n;x++){
if(du[x]!=2) continue;
int a=0,b=0,u,v;
for(int i=head[x];i;i=e[i].next){
if(isv[e[i].to]) continue;
if(!a) a=i,u=e[i].to;
else b=i,v=e[i].to;
}
if(u==v) continue;
isv[x]=1,du[u]--,du[v]--;
LL l_0=(e[a].a*e[b].a%mod+e[a].b*e[b].b%mod*(k-1)%mod)%mod;
LL l_1=(e[a].a*e[b].b%mod+e[a].b*e[b].a%mod+e[a].b*e[b].b%mod*(k-2)%mod)%mod;
add(u,v,l_0,l_1);
}
}
LL C(int n,int m){
return ml[n]*inv[m]%mod*inv[n-m]%mod;
}
int main(){
freopen("color.in","r",stdin);
freopen("color.out","w",stdout);
cin>>n>>m>>k;e.push_back(edge(0,0,0,0));
for(int i=1,u,v;i<=m;i++) scanf("%d%d",&u,&v),add(u,v,0,1);
del_1(),del_2();
for(int i=1;i<=n;i++) if(!isv[i]) t[++tot]=i,id[i]=tot;
if(!tot){cout<<ans*k%mod;return 0;}
for(int x=1;x<=tot;x++) for(int i=head[t[x]];i;i=e[i].next){
int y=e[i].to;
if(isv[y]) continue;
g[x].push_back(edge(id[y],0,e[i].a,e[i].b));
}
for(int s=1;s<(1<<tot);s++){
val[s]=1;
for(int x=1;x<=tot;x++) if(s&(1<<x-1))
for(int i=0;i<g[x].size();i++){
int y=g[x][i].to;
if(s&(1<<y-1)&&y<x) val[s]=val[s]*g[x][i].a%mod;
}
}
f[0][0]=ml[0]=inv[0]=inv[1]=1;
for(int i=1;i<=k;i++) ml[i]=ml[i-1]*i%mod;
for(int i=2;i<=k;i++) inv[i]=(mod-mod/i)*inv[mod%i]%mod;
for(int i=2;i<=k;i++) inv[i]=inv[i]*inv[i-1]%mod;
for(int i=0;i<tot;i++){
for(int s=0;s<(1<<tot);s++) if(f[i][s]){
int S=((1<<tot)-1)^s;
for(int j=S;j;j=j-1&S){
LL now=1;
for(int x=1;x<=tot;x++)if(j&(1<<x-1))
for(int y=0;y<g[x].size();y++) if(s&(1<<g[x][y].to-1)) now=now*g[x][y].b%mod;
f[i+1][j|s]=(f[i+1][j|s]+f[i][s]*now%mod*val[j]%mod)%mod;
}
}
sum=(sum+f[i+1][(1<<tot)-1]*C(k,i+1)%mod)%mod;
}
cout<<ans*sum%mod;
return 0;
}
jzoj 6080 IOer
https://jzoj.net/senior/#contest/show/2681/1
emmmmm
看不懂,直接粘题解。
代码还是好打的。
呵呵
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#define LL long long
using namespace std;
const int MAXN=2e5+5;
const int mod=998244353;
int T;
LL n,m,u,v,ml[MAXN],inv[MAXN];
LL C(LL n,LL m){
return ml[n]*inv[n-m]%mod*inv[m]%mod;
}
LL Pow(LL a,LL b){
LL ans=1;
a%=mod;
while(b){
if(b&1) ans=ans*a%mod;
a=a*a%mod;
b>>=1;
}
return ans;
}
LL calc(){
LL ans=0;
for(int i=0;i<m;i++){
LL now=C(m-1,i)*Pow((m-i)*u+v,n+m-1)%mod;
if(i%2) now=(-now+mod)%mod;
ans=(ans+now)%mod;
}
return ans*inv[m-1]%mod*Pow(Pow(u,m-1),mod-2)%mod;
}
int main(){
freopen("ioer.in","r",stdin);
freopen("ioer.out","w",stdout);
cin>>T;ml[0]=inv[0]=inv[1]=1;
for(int i=1;i<=2e5;i++) ml[i]=ml[i-1]*i%mod;
for(int i=2;i<=2e5;i++) inv[i]=(mod-mod/i)*inv[mod%i]%mod;
for(int i=2;i<=2e5;i++) inv[i]=inv[i]*inv[i-1]%mod;
while(T--){
cin>>n>>m>>u>>v;
cout<<calc()<<endl;
}
return 0;
}
标签:int,LL,修仙,3.25,ans,MAXN,include,mod 来源: https://blog.csdn.net/qq_41709770/article/details/88802235