QOJ.ac
QOJ
ID | 题目 | 提交者 | 结果 | 用时 | 内存 | 语言 | 文件大小 | 提交时间 | 测评时间 |
---|---|---|---|---|---|---|---|---|---|
#334183 | #6954. Almost Acyclic | chenxinyang2006 | AC ✓ | 859ms | 12876kb | C++14 | 8.2kb | 2024-02-21 12:53:09 | 2024-02-21 12:53:10 |
Judging History
answer
#include <bits/stdc++.h>
#define rep(i,j,k) for(int i=(j);i<=(k);i++)
#define per(i,j,k) for(int i=(j);i>=(k);i--)
#define uint unsigned int
#define ll long long
#define ull unsigned long long
#define db double
#define ldb long double
#define pii pair<int,int>
#define pll pair<ll,ll>
#define mkp make_pair
#define eb emplace_back
#define SZ(S) (int)S.size()
//#define mod 998244353
#define mod 1000000007
#define inf 0x3f3f3f3f
#define linf 0x3f3f3f3f3f3f3f3f
using namespace std;
template <class T>
void chkmax(T &x,T y){
if(x < y) x = y;
}
template <class T>
void chkmin(T &x,T y){
if(x > y) x = y;
}
inline int popcnt(int x){
return __builtin_popcount(x);
}
inline int ctz(int x){
return __builtin_ctz(x);
}
template <int P>
class mod_int
{
using Z = mod_int;
private:
static int mo(int x) { return x < 0 ? x + P : x; }
public:
int x;
int val() const { return x; }
mod_int() : x(0) {}
template <class T>
mod_int(const T &x_) : x(x_ >= 0 && x_ < P ? static_cast<int>(x_) : mo(static_cast<int>(x_ % P))) {}
bool operator==(const Z &rhs) const { return x == rhs.x; }
bool operator!=(const Z &rhs) const { return x != rhs.x; }
Z operator-() const { return Z(x ? P - x : 0); }
Z pow(long long k) const
{
Z res = 1, t = *this;
while (k)
{
if (k & 1)
res *= t;
if (k >>= 1)
t *= t;
}
return res;
}
Z &operator++()
{
x < P - 1 ? ++x : x = 0;
return *this;
}
Z &operator--()
{
x ? --x : x = P - 1;
return *this;
}
Z operator++(int)
{
Z ret = x;
x < P - 1 ? ++x : x = 0;
return ret;
}
Z operator--(int)
{
Z ret = x;
x ? --x : x = P - 1;
return ret;
}
Z inv() const { return pow(P - 2); }
Z &operator+=(const Z &rhs)
{
(x += rhs.x) >= P && (x -= P);
return *this;
}
Z &operator-=(const Z &rhs)
{
(x -= rhs.x) < 0 && (x += P);
return *this;
}
Z operator-()
{
return -x;
}
Z &operator*=(const Z &rhs)
{
x = 1ULL * x * rhs.x % P;
return *this;
}
Z &operator/=(const Z &rhs) { return *this *= rhs.inv(); }
#define setO(T, o) \
friend T operator o(const Z &lhs, const Z &rhs) \
{ \
Z res = lhs; \
return res o## = rhs; \
}
setO(Z, +) setO(Z, -) setO(Z, *) setO(Z, /)
#undef setO
friend istream& operator>>(istream& is, mod_int& x)
{
long long tmp;
is >> tmp;
x = tmp;
return is;
}
friend ostream& operator<<(ostream& os, const mod_int& x)
{
os << x.val();
return os;
}
};
using Z = mod_int<mod>;
const Z i2 = 500000004;
Z power(Z p,ll k){
Z ans = 1;
while(k){
if(k % 2 == 1) ans *= p;
p *= p;
k /= 2;
}
return ans;
}
int TEST,n;
Z G[20][20],degsum[16][1 << 16];
int rmv(int p,int S){
int res = S & ((1 << p) - 1);
res |= (S >> (p + 1)) << p;
return res;
}
Z M[20][20];
Z getdet(int K){//[1,K]
Z res = 1;
rep(i,1,K){
int pos = -1;
rep(j,i,K) if(M[j][i].val()) pos = j;
if(pos == -1) return 0;
if(pos != i){
res *= -1;
rep(k,1,K) swap(M[pos][k],M[i][k]);
}
Z iv = Z(1) / M[i][i];
rep(j,i + 1,K){
Z r = M[j][i] * iv;
rep(k,1,K) M[j][k] -= M[i][k] * r;
}
}
rep(i,1,K) res *= M[i][i];
return res;
}
Z E[20][20];
Z matrix_tree(int K){//对边集 E 做生成树计数
if(!K) return 0;
memset(M,0,sizeof(M));
rep(i,1,K){
rep(j,i + 1,K){
M[i][j] -= E[i][j];
M[j][i] -= E[i][j];
M[i][i] += E[i][j];
M[j][j] += E[i][j];
}
}
rep(i,1,K) M[i][1] = M[1][i] = 0;
M[1][1] = 1;
return getdet(K);
}
int qid[20];
Z val[1 << 16],qval[1 << 16];
#define lowbit(x) (x & (-x))
Z f[1 << 16];//子集划分
Z calc(int s){
f[0] = 1;
rep(S,1,(1 << s) - 1){
f[S] = 0;
int p = 1 << __lg(S),R = S - p,T;
for(int T0 = R;;T0 = (T0 - 1) & R){
T = T0 | p;
f[S] += qval[T] * f[S ^ T];
if(!T0) break;
}
}
return f[(1 << s) - 1];
}
Z spcalc(int s){
f[0] = 1;
rep(S,1,(1 << s) - 1){
if((S & (1 << (s - 1))) && S + 1 != (1 << s)) continue;
f[S] = 0;
int p = 1 << __lg(S),R = S - p,T;
for(int T0 = R;;T0 = (T0 - 1) & R){
T = T0 | p;
f[S] += qval[T] * f[S ^ T];
if(!T0) break;
}
}
return f[(1 << s) - 1];
}
Z dp[1 << 16][16];
void solve(){
scanf("%d",&n);
memset(dp,0,sizeof(dp));
rep(u,1,n){
rep(v,1,n){
int temp;
scanf("%d",&temp);
G[u][v] = temp;
}
}
Z answer = 0,cur;
int cnt;
val[1] = 1;
rep(u,2,n){
rep(S,1,(1 << (u - 1)) - 1){
qval[S] = val[S];
cur = 0;
rep(k,0,u - 2) if((S >> k) & 1) cur += G[k + 1][u];
qval[S] *= cur;
}
calc(u - 1);
rep(S,0,(1 << (u - 1)) - 1) val[S + (1 << (u - 1))] = f[S];
}
rep(u,1,n){
rep(S,0,(1 << n) - 1){
if(S & (1 << (u - 1))) continue;
int T = rmv(u - 1,S);
cur = 1;
rep(k,0,n - 1) if((S >> k) & 1) cur = cur * (G[u][k + 1] + 1);
qval[T] = val[S] * (cur - 1);
}
answer += spcalc(n - 1);
}
rep(u,0,n - 1){
rep(S,1,(1 << n) - 1) degsum[u][S] = degsum[u][S - lowbit(S)] + G[u + 1][ctz(S) + 1];
}
rep(u,1,n){
rep(v,u + 1,n){
rep(S,0,(1 << n) - 1){
if(S & (1 << (u - 1)) || S & (1 << (v - 1))) continue;
int T = rmv(u - 1,rmv(v - 1,S));
qval[T] = val[S] * ((1 + degsum[u - 1][S]) * (1 + degsum[v - 1][S]) - 1);
}
answer -= (G[u][v] + 1) * spcalc(n - 2);
//这里多减去了 0~2 交的 case
}
}
rep(S,1,(1 << n) - 1) if(S & 1) answer += val[S] * val[(1 << n) - 1 - S] * popcnt(S) * (n - popcnt(S));//0 交*/
rep(i,1,n){
rep(j,i + 1,n){
E[i][j] = G[i][j];
}
}
Z sp = matrix_tree(n);
answer += sp * n * (n - 1) / 2;//1 交
answer -= sp * (n - 1);//过量计数
Z sum;
per(s,n - 1,0){
rep(S,0,(1 << (s + 1)) - 1) fill(dp[S],dp[S] + s + 1,0);
dp[1 << s][s] = 1;
rep(S,0,(1 << (s + 1)) - 1){
rep(u,0,s){
if(!((S >> u) & 1)) continue;
rep(v,0,s){
if((S >> v) & 1) continue;
dp[S + (1 << v)][v] += dp[S][u] * G[u + 1][v + 1];
}
}
}
rep(S,0,(1 << (s + 1)) - 1){
int k = popcnt(S);
if(!((S >> s) & 1) || k < 3) continue;
sum = 0;
rep(u,0,s){
if(!(S >> u) & 1) continue;
sum += dp[S][u] * G[u + 1][s + 1];
}
sum *= i2;//正反转
cnt = 1;
rep(u,0,n - 1){
if((S >> u) & 1) qid[u + 1] = 1;
else qid[u + 1] = ++cnt;
}
memset(E,0,sizeof(E));
rep(u,1,n){
rep(v,1,n){
if(qid[u] != qid[v]) E[qid[u]][qid[v]] += G[u][v];
}
}
sum *= matrix_tree(cnt);
answer += sum * k * (k - 1) * i2;//2 交
answer -= sum * (k - 1);//过量计数
}
}
printf("%d\n",answer.val());
}
int main(){
// freopen("test.in","r",stdin);
// freopen("test.out","w",stdout);
scanf("%d",&TEST);
while(TEST--) solve();
cerr << clock() << endl;
return 0;
}
详细
Test #1:
score: 100
Accepted
time: 859ms
memory: 12876kb
input:
16 1 0 2 0 953763239 953763239 0 3 0 734999893 771971068 734999893 0 980773372 771971068 980773372 0 4 0 295218414 142837698 715328025 295218414 0 833169030 224028769 142837698 833169030 0 450275651 715328025 224028769 450275651 0 5 0 168127828 27116722 242318695 817220009 168127828 0 719973784 3288...
output:
1 953763239 858912196 425387299 913279760 958445240 55200517 150069607 303235124 105856735 869632234 877416619 919519535 312800965 893593717 127611854
result:
ok 16 lines