for (int i = 1; i <= n; i ++) for (int j = 1; j <= n; j ++) for (int k = 1; k <= n; k ++) a[i][j][k] += a[i - 1][j][k] for (int i = 1; i <= n; i ++) for (int j = 1; j <= n; j ++) for (int k = 1; k <= n; k ++) a[i][j][k] += a[i][j - 1][k] for (int i = 1; i <= n; i ++) for (int j = 1; j <= n; j ++) for (int k = 1; k <= n; k ++) a[i][j][k] += a[i][j][k - 1]
inlineintlowbit(int x){ return x & (- x); } int mp[MAXM]= {0}, pcnt[MAXM]= {0}; LL power(LL x, int p){ LL cnt = 1; while (p) { if (p & 1) cnt = cnt * x % MOD; x = x * x % MOD, p >>= 1; } return cnt; }
int N, M; int a[MAXK], p[MAXK];
int suma[KTRS]= {0}; LL sump[KTRS]= {0}, undp[KTRS]= {0};
int zocnt[MAXM]= {0}; LL f[MAXM]= {0};
LL g[MAXM]= {0};
inlineintgetnum(){ int num = 0; char ch = getchar (); while (! isdigit (ch)) ch = getchar (); while (isdigit (ch)) num = (num << 3) + (num << 1) + ch - '0', ch = getchar (); return num; }
intmain(){ N = getnum (), M = getnum (); int lim = (1 << M) - 1; for (int i = 2; i <= lim; i ++) mp[i] = mp[i >> 1] + 1; for (int i = 1; i <= lim; i ++) pcnt[i] = pcnt[i >> 1] + (i & 1); for (int i = 0; i <= lim; i ++) f[i] = 1; for (int i = 1; i <= N; i ++) { int K = getnum (), d = 0; for (int j = 0; j < K; j ++) { a[j] = getnum (), p[j] = getnum (); d += p[j]; } int poe = power (1ll * d, MOD - 2); for (int j = 0; j < K; j ++) p[j] = 1ll * p[j] * poe % MOD; int lik = (1 << K) - 1; sump[0] = undp[0] = 0; for (int j = 1; j <= lik; j ++) { suma[j] = suma[j ^ lowbit (j)] | a[mp[lowbit (j)]]; sump[j] = (sump[j ^ lowbit (j)] + p[mp[lowbit (j)]]) % MOD; undp[j] = power (sump[j], MOD - 2); } sump[0] = undp[0] = 1; for (int j = 0; j < K; j ++) { int l = 1 << j; for (int k = 0; k <= lik; k ++) if (k & l) { sump[k] = sump[k] * undp[k ^ l] % MOD; undp[k] = undp[k] * sump[k ^ l] % MOD; } } zocnt[0] ++; for (int j = 1; j <= lik; j ++) { if (pcnt[j] & 1) zocnt[suma[j]] --; else zocnt[suma[j]] ++; f[suma[j]] = f[suma[j]] * sump[j] % MOD; } } for (int i = 0; i < M; i ++) { int l = 1 << i; for (int j = 0; j <= lim; j ++) if (j & l) { f[j] = f[j] * f[j ^ l] % MOD; zocnt[j] += zocnt[j ^ l]; } } for (int i = 0; i <= lim; i ++) { if (zocnt[i] > 0) g[i] = 0; else g[i] = f[i]; } for (int i = 0; i < M; i ++) { int l = 1 << i; for (int j = 0; j <= lim; j ++) if (j & l) g[j] = (g[j] - g[j ^ l] + MOD) % MOD; // 注意这里使容斥,某个g[j]被减两次则变成加 } LL ans = 0; for (int j = 0; j <= lim; j ++) ans ^= g[j]; cout << ans << endl;
int N, M; LL f[MAXN][MAXN]= {0}; int rnk[MAXN][MAXN]= {0};
inlineintgetnum(){ int num = 0; char ch = getchar (); while (! isdigit (ch)) ch = getchar (); while (isdigit (ch)) num = (num << 3) + (num << 1) + ch - '0', ch = getchar (); return num; }
intmain(){ N = getnum (), M = getnum (); for (int i = 1; i <= N; i ++) for (int j = i + 1; j <= N; j ++) f[i][j] = f[j][i] = INF; for (int i = 1; i <= M; i ++) { int u = getnum (), v = getnum (), w = getnum (); f[u][v] = f[v][u] = w; } for (int k = 1; k <= N; k ++) for (int i = 1; i <= N; i ++) for (int j = 1; j <= N; j ++) f[i][j] = min (f[i][j], f[i][k] + f[k][j]); for (int i = 1; i <= N; i ++) { for (int j = 1; j <= N; j ++) rnk[i][j] = j; for (int j = 1; j <= N; j ++) for (int k = j + 1; k <= N; k ++) if (f[i][rnk[i][j]] > f[i][rnk[i][k]]) swap (rnk[i][j], rnk[i][k]); } LL ans = INF; for (int u = 1; u <= N; u ++) for (int v = 1; v <= N; v ++) { ans = min (ans, f[u][rnk[u][N]] << 1); // 中心取端点处 ans = min (ans, f[v][rnk[v][N]] << 1); int k = N; for (int i = N - 1; i >= 1; i --) if (f[v][rnk[u][i]] > f[v][rnk[u][k]]) { // 判断两折线是否有交 ans = min (ans, f[u][rnk[u][i]] + f[u][v] + f[v][rnk[u][k]]); k = i; } } cout << ans << endl;