18.10.31 考试总结
今天考试总算开始走入正轨了 早上强行逼着自己不去睡觉...。 把T1肝出来了... 不容易 T3是原题 最后二十分钟爆手速95分 少判了个重边
这道题是一道推公式的题目 因为所有的格子都是由之前的格子推过来的 所以可以忽略中间部分的格子 只考虑给出的格子
首先可以发现$(1, 1)$毫无用处 继续考虑每个格子的数向下之后会乘$b$向右乘$a$
所以将格子初始考虑成水流将贡献分开计算 最终流向$(n, n)$
每流一格自身的贡献会乘上一个系数并对这个格子产生贡献 所以考虑它有多少种产生贡献的方法 显然总的路程是知道的
所以路程数取一下组合数即可 他路径中的贡献就是$t * a^{x} * b^{y},x$是总路程中向右走的次数 $y$是向左走的次数$t$是初始值
代码
#include <bits/stdc++.h> #define il inline #define rg register using namespace std; typedef long long ll; const int N = 1e6 + 5; const ll MOD = 1e9 + 7; ll ans, fac[N], rfac[N], n, a, b; il ll read( ) { ll t = 1, ans = 0; char x; x = getchar( ); while(x < '0' || x > '9') { if(x == '-') t - 1; x = getchar( ); } while(x >= '0' && x <= '9') { ans = ans * 10 + x - '0'; x = getchar( ); } return ans * t; } il ll fast_pow(ll a, ll b) { ll ans = 1; for(;b;b >>= 1, a = a * a % MOD) if(b & 1) ans = ans * a % MOD; return ans; } il void Init( ) { n = read( ), b = read( ), a = read( ); fac[0] = 1; rfac[0] = 1; for(rg int i = 1;i <= 2 * n;i ++) { fac[i] = fac[i - 1] * i % MOD; rfac[i] = fast_pow(fac[i], MOD - 2); } } il ll C(ll a, ll b) { if(b > a) return 0; return fac[a] * rfac[a - b] % MOD * rfac[b] % MOD; } il void Solve( ) { for(rg int i = 1;i <= n;i ++) { ll t; t = read( ); if(i == 1) continue; ll x = 2, y = i; ll len = n - x + n - y, lenb = n - x, lena = n - y; ll del = t * b % MOD * C(len, lenb) % MOD * fast_pow(b, lenb) % MOD * fast_pow(a, lena) % MOD; ans = (ans + del) % MOD; } for(rg int i = 1;i <= n;i ++) { ll t; t = read( ); if(i == 1) continue; ll x = i, y = 2; ll len = n - x + n - y, lenb = n - x, lena = n - y; ll del = t * a % MOD * C(len, lenb) % MOD * fast_pow(b, lenb) % MOD * fast_pow(a, lena) % MOD; ans = (ans + del) % MOD; } printf("%lld\n", ans); } int main( ) { freopen("matrix.in", "r", stdin); freopen("matrix.out", "w", stdout); Init( ); Solve( ); }
这道题考试的时候觉得是贪心.. 但是这数据范围一看就不是贪心 所以就打了个暴搜
使用记忆化搜索 首先发现取数的次数满足二分性 所以考虑二分
每次搜索的时候对当前位置的数枚举它能够放$i$个$p$ 放$q$是有限制的 限制为$all - i$
因为题目保证取出数的时候不能从一个数里取 所以这个数里取出$i$个$p$至少需要在外面的数取$i$个$q$
也就是里面不能取超过$all - i$个$q$ 记忆化搜索即可 复杂度相当于填表 而且还填不满 略玄学
代码
#include <bits/stdc++.h> #define oo 1e6 #define il inline #define rg register using namespace std; const int N = 1005; int n, p, q, a[N], sum[N], vis[51][N][N], idc, all; il int read( ) { int t = 1, ans = 0; char x; x = getchar( ); while(x < '0' || x > '9') { if(x == '-') t - 1; x = getchar( ); } while(x >= '0' && x <= '9') { ans = ans * 10 + x - '0'; x = getchar( ); } return ans * t; } void Init( ) { n = read( ); if(p < q) swap(p, q); for(int i = 1;i <= n;i ++) a[i] = read( ); p = read( ), q = read( ); for(int i = n;i >= 1;i --) sum[i] = sum[i + 1] + a[i]; } bool dfs(int dep, int nump, int numq) { if(! nump && ! numq) return true; if((dep == n + 1) || sum[dep] < nump * p + numq * q) return false; if(vis[dep][nump][numq] == idc) return false; for(int i = 0;i <= min(a[dep] / p, nump);i ++) if(dfs(dep + 1, nump - i, max(0, numq - min((a[dep] - i * p) / q, all - i)))) return true; vis[dep][nump][numq] = idc; return false; } bool check(int mid) { idc ++; all = mid; return dfs(1, mid, mid); } void Solve( ) { int l = 0, r = sum[1] / (p + q) + 1, ans = 0; while(l <= r) { int mid = l + r >> 1; if(check(mid)) ans = mid, l = mid + 1; else r = mid - 1; } printf("%lld", 1ll * ans * (p + q)); } int main( ) { freopen("pq.in", "r", stdin); freopen("pq.out", "w", stdout); Init( ); Solve( ); }
对不起这是一道原题..。 最后爆手速赶出来了
多起点多重点$spfa$即可 记得判重边 我这里掉了五分
代码
#include <bits/stdc++.h> #define il inline #define rg register #define oo 1e9 using namespace std; const int N = 3 * 1e4 + 5; const int M = 2 * 1e5 + 5; int n, m, head[N], nex[M], tov[M], val[M], tot = 1; int dis[N], ee[N], len[N], ans; bool vis[N]; queue<int>Q; il int read( ) { int t = 1, ans = 0; char x; x = getchar( ); while(x < '0' || x > '9') { if(x == '-') t - 1; x = getchar( ); } while(x >= '0' && x <= '9') { ans = ans * 10 + x - '0'; x = getchar( ); } return ans * t; } il void add(int u, int v, int w) { tot ++; nex[tot] = head[u]; tov[tot] = v; val[tot] = w; head[u] = tot; } il void Init( ) { n = read( ), m = read( ); for(rg int i = 1;i <= m;i ++) { int u, v, w1, w2; u = read( ), v = read( ), w1 = read( ), w2 = read( ); add(u, v, w1); add(v, u, w2); } } il void spfa(int st) { memset(dis, 0x3f3f3f3f, sizeof(dis)); memset(vis, 0, sizeof(vis)); memset(len, 0x3f3f3f3f, sizeof(len)); for(rg int i = head[1];i;i = nex[i]) { int v = tov[i]; len[v] = min(len[v], val[i ^ 1]); if(v & (1 << (st - 1))) { vis[v] = true; Q.push(v); dis[v] = min(dis[v], val[i]); } } while(! Q.empty( )) { int u = Q.front( ); Q.pop( ); vis[u] = false; for(rg int i = head[u];i;i = nex[i]) { int v = tov[i]; if(v == 1) continue; if(dis[v] > dis[u] + val[i]) { dis[v] = dis[u] + val[i]; if(! vis[v]) { Q.push(v); vis[v] = true; } } } } for(int i = head[1];i;i = nex[i]) { int v = tov[i]; if(! (v & (1 << (st - 1)))) { ans = min(ans, dis[v] + len[v]); } } memset(dis, 0x3f3f3f3f, sizeof(dis)); memset(vis, 0, sizeof(vis)); for(rg int i = head[1];i;i = nex[i]) { int v = tov[i]; len[v] = min(len[v], val[i ^ 1]); if(!(v & (1 << (st - 1)))) { vis[v] = true; Q.push(v); dis[v] = min(dis[v], val[i]); } } while(! Q.empty( )) { int u = Q.front( ); Q.pop( ); vis[u] = false; for(rg int i = head[u];i;i = nex[i]) { int v = tov[i]; if(v == 1) continue; if(dis[v] > dis[u] + val[i]) { dis[v] = dis[u] + val[i]; if(! vis[v]) { Q.push(v); vis[v] = true; } } } } for(rg int i = head[1];i;i = nex[i]) { int v = tov[i]; if(v & (1 << (st - 1))) { ans = min(ans, dis[v] + len[v]); } } } int main( ) { freopen("graph.in", "r", stdin); freopen("graph.out", "w", stdout); Init( ); ans = oo; int h = 0; for(int i = head[1]; i; i = nex[i]) { int v = tov[i]; for(int j = 30;j >= 1;j --) { if(v & (1 << (j - 1))) { h = max(h, j); break; } } } for(int i = 1;i <= h;i ++) { spfa(i); } printf("%d\n", ans); }