【10.31校内测试】【组合数学】【记忆化搜索/DP】【多起点多终点二进制拆位Spfa】

【10.31校内测试】【组合数学】【记忆化搜索/DP】【多起点多终点二进制拆位Spfa】

Solution

【10.31校内测试】【组合数学】【记忆化搜索/DP】【多起点多终点二进制拆位Spfa】

注意取模!!!

Code

#include<bits/stdc++.h>
#define mod 1000000007
#define LL long long
using namespace std; int n, a, b; LL mpow(LL a, LL b) {
LL ans = ;
for(; b; b >>= , a = a * a % mod)
if(b & ) ans = ans * a % mod;
return ans;
} LL fac[], inv[], l[], t[];
void init() {
fac[] = ;
inv[] = ;
for(int i = ; i <= ; i ++) {
fac[i] = fac[i - ] * i % mod;
inv[i] = mpow(fac[i], mod - );
}
} LL C(int p, int q) {
return fac[p] * inv[q] % mod * inv[p - q] % mod;
} int main() {
freopen("matrix.in", "r", stdin);
freopen("matrix.out", "w", stdout);
scanf("%d%d%d", &n, &b, &a);
for(int i = ; i <= n; i ++) scanf("%lld", &l[i]);
for(int i = ; i <= n; i ++) scanf("%lld", &t[i]);
LL ans = ;
init();
for(int i = ; i <= n; i ++) {
ans = (ans + b * l[i] % mod * C(n - + n - i, n - ) % mod * mpow(a, n - i) % mod * mpow(b, n - ) % mod) % mod;
ans = (ans + a * t[i] % mod * C(n - + n - i, n - ) % mod * mpow(b, n - i) % mod * mpow(a, n - ) % mod) % mod;
}
printf("%lld", ans);
return ;
}

【10.31校内测试】【组合数学】【记忆化搜索/DP】【多起点多终点二进制拆位Spfa】

【10.31校内测试】【组合数学】【记忆化搜索/DP】【多起点多终点二进制拆位Spfa】

Solution

二分+DP,二分需要多少组p+q,记忆化搜索判断是否可以达到条件。

定义$dp[dep][j][k]$表示当前取到第$dep$个数,还需要j个p,k个q来使满足条件。(p>q)

每次先尽量放p,剩下中再尽量放q,放q时就有限制,不能取超过$mid-i$,i表示当前取的p的数量。

Code

#include<bits/stdc++.h>
using namespace std; int n, a[], p, q;
int sum[], vis[][][], tim, all;
bool dfs(int dep, int nump, int numq) {
if(nump == && numq == ) return ;
if(dep == n + || sum[dep] < nump * p + numq * q) return ;
if(vis[dep][nump][numq] == tim) return ;
for(int i = ; i <= min(nump, a[dep] / p); i ++)
if(dfs(dep + , nump - i, max(numq - min((a[dep] - p * i) / q, all - i), ))) return ;
vis[dep][nump][numq] = tim;
return ;
} bool check(int mid) {
tim ++;
all = mid;
return dfs(, mid, mid);
} int erfen() {
int l = , r = sum[] / (p + q), ans;
while(l <= r) {
int mid = (l + r) >> ;
if(check(mid)) ans = mid, l = mid + ;
else r = mid - ;
}
return ans;
} int main() {
freopen("pq.in", "r", stdin);
freopen("pq.out", "w", stdout);
scanf("%d", &n);
for(int i = ; i <= n; i ++) scanf("%d", &a[i]);
for(int i = n; i >= ; i --) sum[i] = sum[i + ] + a[i];
scanf("%d%d", &p, &q);
if(p < q) swap(p, q);
int ans = erfen();
printf("%d", ans * (p + q));
return ;
}

【10.31校内测试】【组合数学】【记忆化搜索/DP】【多起点多终点二进制拆位Spfa】

【10.31校内测试】【组合数学】【记忆化搜索/DP】【多起点多终点二进制拆位Spfa】

Solution

考试最后半小时开始写QAQ结果发现是做过的题啊??

可是最后Spfa写错了!!!我爆哭!!!!

将与1相连的所有点取出来,二进制分类,分成起点和终点,跑多起点多终点的Spfa,处理出两两起点终点间最短路,更新答案即可QAQ

Spfa要判更新的点不能是1!!

Code

#include<bits/stdc++.h>
using namespace std; int n, m; struct Node {
int v, nex, w;
} Edge[]; int h[], stot = ;
void add(int u, int v, int w) {
Edge[++stot] = (Node) {v, h[u], w};
h[u] = stot;
} int dis[];
int vis[], nums, numt, w[], t[], S[], T[];
void Spfa1() {
queue < int > q;
memset(vis, , sizeof(vis));
memset(dis, 0x3f3f3f3f, sizeof(dis));
for(int i = ; i <= nums; i ++) q.push(S[i]), vis[S[i]] = , dis[S[i]] = min(dis[S[i]], w[S[i]]);
while(!q.empty()) {
int u = q.front(); q.pop(); vis[u] = ;
for(int i = h[u]; i; i = Edge[i].nex) {
int v = Edge[i].v;
if(dis[v] > dis[u] + Edge[i].w && v != ) {
dis[v] = dis[u] + Edge[i].w;
if(!vis[v]) {
vis[v] = ; q.push(v);
}
}
}
}
} void Spfa2() {
queue < int > q;
memset(vis, , sizeof(vis));
memset(dis, 0x3f3f3f3f, sizeof(dis));
for(int i = ; i <= numt; i ++) q.push(T[i]), vis[T[i]] = , dis[T[i]] = min(dis[T[i]], w[T[i]]);
while(!q.empty()) {
int u = q.front(); q.pop(); vis[u] = ;
for(int i = h[u]; i; i = Edge[i].nex) {
int v = Edge[i].v;
if(dis[v] > dis[u] + Edge[i].w && v != ) {
dis[v] = dis[u] + Edge[i].w;
if(!vis[v]) {
vis[v] = ; q.push(v);
}
}
}
}
} int tov[], tot;
int main() {
freopen("graph.in", "r", stdin);
freopen("graph.out", "w", stdout);
scanf("%d%d", &n, &m);
for(int i = ; i <= m; i ++) {
int u, v, a, b;
scanf("%d%d%d%d", &u, &v, &a, &b);
add(u, v, a); add(v, u, b);
}
int ans = 0x3f3f3f3f;
memset(w, 0x3f3f3f3f, sizeof(w));
memset(t, 0x3f3f3f3f, sizeof(t));
for(int i = h[]; i; i = Edge[i].nex)
tov[++tot] = Edge[i].v, w[Edge[i].v] = min(w[Edge[i].v], Edge[i].w), t[Edge[i].v] = min(t[Edge[i].v], Edge[i ^ ].w);
sort(tov + , tov + + tot);
int M = tov[tot], tt = ;
while(M) {
int tmp = (M & );
nums = , numt = ;
for(int i = ; i <= tot; i ++)
if(((tov[i] >> tt) & ) == tmp) S[++nums] = tov[i];
else T[++numt] = tov[i];
Spfa1();
for(int j = ; j <= numt; j ++) {
ans = min(ans, t[T[j]] + dis[T[j]]);
}
Spfa2();
for(int j = ; j <= nums; j ++) {
ans = min(ans, t[S[j]] + dis[S[j]]);
}
M >>= , tt ++;
}
printf("%d", ans);
return ;
}
上一篇:Spring Boot -05- 多模块结构项目构建与测试(详细图文教程)IDEA 版


下一篇:在虚拟机中安装红旗桌面7.0 Linux操作系统的详细图文教程