
#include <bits/stdc++.h> using namespace std; const int maxn = 1e5 + 50; typedef long long ll; const ll mod = 1e9 + 7; ll fac[maxn], sing[maxn], inv[maxn]; void init(int n) { fac[0] = sing[0] = inv[0] = fac[1] = sing[1] = inv[1] = 1; for(int i = 2; i <= n; i++) { fac[i] = fac[i - 1] * i % mod; sing[i] = (mod - mod / i) * sing[mod % i] % mod; inv[i] = inv[i - 1] * sing[i] % mod; } } ll C(int n, int m) { ll res = fac[n]* inv[m] % mod * inv[n - m] % mod; // printf("%d %d %lld ",n, m, res); return res; } struct Seg { int l, r, belong, id; }seg[maxn]; ll ans[maxn]; bool cmp(Seg A, Seg B) { if(A.belong == B.belong) return A.r < B.r; return A.l < B.l; } int main() { init(1e5 + 5); int block = sqrt(1e5); int T; scanf("%d", &T); for(int p = 1; p <= T; p++) { scanf("%d %d", &seg[p].l, &seg[p].r); seg[p].belong = seg[p].l / block; seg[p].id = p; } sort(seg + 1, seg + T + 1, cmp); int l = 0, r = 0; ll res = 1; for(int i = 1; i <= T; i++) { while(l < seg[i].l) { res = (res * 2LL % mod + mod - C(l, r)) % mod; l++; } while(l > seg[i].l) { l--; res = (res + C(l, r)) * sing[2] % mod; } while(r < seg[i].r) { r++; res = (res + C(l, r)) % mod; } while(r > seg[i].r) { res = (res + mod - C(l, r)) % mod; r--; } ans[seg[i].id] = res; // printf("%lld ", ans[seg[i].id]); } for(int i = 1; i <= T; i++) { printf("%lld ", ans[i]); } return 0; }

#include <bits/stdc++.h> using namespace std; typedef long long ll; const int maxn = 1e3 + 50; int a[maxn]; int sum = 0; int m[50][50]; int L; ll solve(ll x, ll y) { x++, y++; ll res = 0; int cntx = x / (2 * L); int cnty = y / (2 * L); res += (ll)cntx * cnty * sum; ///加上整块的 int tempx = x - cntx * 2 * L; int tempy = y - cnty * 2 * L; ll sum1 = 0 ,sum2 = 0; for(int i = 0; i < tempx; i++) ///加上半块半块的 { for(int j = 0; j < 2 * L; j++) { sum1 += m[i][j]; } } for(int i = 0; i < 2 * L; i++) { for(int j = 0; j < tempy; j++) { sum2 += m[i][j]; } } res += sum1 * cnty; res += sum2 * cntx; ///加上残块的 for(int i = 0; i < tempx; i++) { for(int j = 0; j < tempy; j++) { res += m[i][j]; } } return res; } int main() { int T; scanf("%d", &T); while(T--) { scanf("%d", &L); sum = 0; for(int i = 0; i < L; i++) scanf("%d", &a[i]), sum += 4 * L * a[i]; int cur = 0; for(int i = 0; i < 45; i++) { for(int j = 0; j <= i; j++) { m[j][i - j] = a[cur]; cur = (cur + 1) % L; } } /* for(int i = 0; i < 10; i++) { for(int j = 0; j < 10; j++) { printf("%3d ", m[i][j]); } printf(" "); }*/ // printf("%lld ",solve(1, 2)); int q; scanf("%d", &q); while(q--) { int x1, y1, x2, y2; scanf("%d %d %d %d", &x1, &y1, &x2, &y2); ll ans = solve(x2, y2) - solve(x2, y1 - 1) - solve(x1 - 1, y2) + solve(x1 - 1, y1 - 1); // printf("%lld %lld %lld %lld ",solve(x2, y2), solve(x2, y1 - 1), solve(x1 - 1, y2), solve(x1 - 1, y1 - 1)); printf("%lld ", ans); } } return 0; }

#include <bits/stdc++.h> using namespace std; char s[20][20], w[5][5]; int vis[50]; int ans = 100; int tmp[5][5]; void Rota(int a, int b) ///顺时针旋转90度 { for(int i = 0; i < 4; i++) { for(int j = 0; j < 4; j++) { tmp[j][3 - i] = s[a + i][b + j]; } } for(int i = 0; i < 4; i++) { for(int j = 0; j < 4; j++) { s[a + i][b + j] = tmp[i][j]; } } } int cnt = 0; int check(int a, int b) { ///memset(vis, 0, sizeof(vis)); 从dls那里学了个姿势,不用每次memset了 for(int i = a; i < a + 4; i++) ///判断我这个小块的前面有没有重复的 { cnt++; for(int j = 0; j < b + 4; j++) { // printf("%d ", s[i][j]); if(vis[s[i][j]] == cnt) { //printf("%d %d %d ", i, j, cnt); return 0; } vis[s[i][j]] = cnt; } } for(int i = b; i < b + 4; i++) { cnt++; for(int j = 0; j < a + 4; j++) { if(vis[s[j][i]] == cnt) return 0; vis[s[j][i]] = cnt; } } return 1; } void dfs(int x, int y, int sum) { if(x == 4) { ans = min(ans, sum); return; } if(sum >= ans) return; if(y == 4) return dfs(x + 1, 0, sum); for(int i = 0; i < 4; i++) { if(check(x * 4, y * 4)) { dfs(x, y + 1, sum + i); } Rota(x * 4, y * 4); } } int main() { int T; scanf("%d", &T); while(T--) { for(int i = 0; i < 16; i++) scanf("%s", s[i]); for(int i = 0; i < 16; i++) { for(int j = 0; j < 16; j++) { s[i][j] = s[i][j] - '0'; } } memset(vis, 0, sizeof(vis)); ans = 100; cnt = 0; dfs(0, 0, 0); printf("%d ", ans); } return 0; }
终于把思路理清楚了。
整体思想是逐位的思想。
首先考虑$b[1]$,我们发现如果$root<b[1]$,那后面怎么排列都满足条件。那我们需要统计这些情况,我们发现每一个点的孩子节点是$deg[i]-1$,只有根节点的孩子节点是$deg[i]$,那我们可以维护一个$res$,令$res=prod_{i=1}^n (deg[i]-1)!$。再计算以$root$为根的排列情况,就$ans += res * deg[root]$就可以了。
考虑完$root<b[1]$的情况,进一步考虑$root=b[1]$的情况。此时先将$res$更新为$res=res*deg[b[1]]$,代表此时以$b[1]$为根出发。和前一种情况类似,走的下一个节点$<b[2]$,那后面怎么排列都满足条件。查询$root$子树中节点$<b[2]$的个数$t$$($可以用$n$颗树状数组解决$)$,那$ans = ans + frac{res*t}{deg[b[1]]}$,就是我从$t$中任选一个点走下一步,$b[1]$少了能任意选择的情况,此时$res$就要修改为$res=frac{res}{deg[b[1]]}$,$deg[b[1]]--$。然后再去考虑$second($第二个遍历点$)=b[2]$的情况。
后面的点依次像上面一样遍历。
慎用$memset!!!$

#include <bits/stdc++.h> using namespace std; typedef long long ll; const int maxn = 1e6 + 50; int b[maxn]; int fac[maxn], sing[maxn], inv[maxn]; int deg[maxn]; vector<int> g[maxn]; const ll mod = 1e9 + 7; void init(int n) { fac[0] = fac[1] = sing[0] = sing[1] = inv[0] = inv[1] = 1; for(int i = 2; i <= n; i++) { fac[i] = (ll)fac[i - 1] * i % mod; sing[i] = (ll)(mod - mod / i) * sing[mod % i] % mod; inv[i] = (ll)inv[i - 1] * sing[i] % mod; } } struct Tree { vector<int> T; int n; void init(int _n) { n = _n; T.resize(n + 1); for(int i = 0; i <= n; i++) T[i] = 0; } void add(int x, int v) { x++; // printf("%d %d ", x, v); for(int i = x; i <= n; i += (i & -i)) T[i] += v; } int query(int x) { x++; //printf("%d ", x); if(x > n) x = n; ///所有的节点都比我小 //printf("%d ", x); int res = 0; for(int i = x; i > 0; i -= (i & -i)) res += T[i]; return res; } }tr[maxn]; int pre[maxn]; void dfs1(int u, int fa) { sort(g[u].begin(), g[u].end()); ///对子节点排序,方便在子节点中离散化存储 pre[u] = fa; tr[u].init(g[u].size()); for(int i = 0; i < g[u].size(); i++) { int v = g[u][i]; if(v == fa) continue; int tmp = lower_bound(g[u].begin(), g[u].end(), v) - g[u].begin(); //printf("%d ", v); tr[u].add(tmp, 1); deg[v]--; dfs1(v, u); } } ll ans = 0, res = 0; int n, cur = 1, flag = 0; void dfs2(int u) { if(cur >= n || flag || (!u)) return; /// !u 退回到根节点 if(deg[u]) ///全部子节点已经被排列 { int tmp = lower_bound(g[u].begin(), g[u].end(), b[cur + 1]) - g[u].begin(); //printf("%d ", b[cur + 1]); int cnt = tr[u].query(tmp - 1); ans = (ans + res * cnt % mod * sing[deg[u]] % mod) % mod; if(pre[b[cur + 1]] != u) ///不用往下继续了,因为给的b序列就不是一个dfs序列 { flag = 1; return; } cur++; tmp = lower_bound(g[u].begin(), g[u].end(), b[cur]) - g[u].begin(); //printf("%d ", b[cur]); tr[u].add(tmp, -1); res = res * sing[deg[u]] % mod; deg[u]--; dfs2(b[cur]); } else dfs2(pre[u]); } int main() { init(1e6); int T; scanf("%d", &T); while(T--) { scanf("%d", &n); for(int i = 1; i <= n; i++) scanf("%d", &b[i]), g[i].clear() ,deg[i] = 0; for(int i = 1; i < n; i++) { int u, v; scanf("%d %d", &u, &v); g[u].push_back(v); g[v].push_back(u); deg[u]++, deg[v]++; } ans = 0, res = 1; for(int i = 1; i <= n; i++) { res = res * fac[deg[i] - 1] % mod; } for(int i = 1; i < b[1]; i++) { ans = (ans + res * deg[i]) % mod; } cur = 1, flag = 0; res = res * deg[b[1]] % mod; dfs1(b[1], 0); dfs2(b[1]); printf("%lld ", ans); } return 0; }