QOJ.ac

QOJ

ID题目提交者结果用时内存语言文件大小提交时间测评时间
#334183#6954. Almost Acyclicchenxinyang2006AC ✓859ms12876kbC++148.2kb2024-02-21 12:53:092024-02-21 12:53:10

Judging History

你现在查看的是最新测评结果

  • [2024-02-21 12:53:10]
  • 评测
  • 测评结果:AC
  • 用时:859ms
  • 内存:12876kb
  • [2024-02-21 12:53:09]
  • 提交

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