在队友的带领下,第一次ak了一场娱乐赛
题目来源:ICPC 2018 Malaysia
没找到链接,Uva上好像有
很多东西都没有自己思考,直接套的板子 or IEOS
A. AKU NEGARAKU
约瑟夫环问题
递归 :
[solve(n,m) = (solve(n-1,m) + m) \% n
]
#include <iostream>
using namespace std;
int solve(int n, int m){
if(1 == n) return 0;
return (solve(n - 1, m) + m) % n;
}
int main(){
int n, m;
while(scanf("%d%d", &n, &m) and n != 0 and m != 0){
printf("%d
", 1 + solve(n,m));
}
}
B. CHEAP DELIVERIES
队友做的,Dij + 状压dp
其实不算很难的一个状压
跟TSP问题差不多
已补
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N = 1e6 + 10;
const int M = 1e6 + 10;
const int K = 40;
typedef long long ll;
const ll inf = 1e18;
struct Edge {
int to, w, next;
}E[M];
int head[M], tot;
void addEdge(int from, int to, int w) {
E[++tot] = Edge{ to,w,head[from] };
head[from] = tot;
}
int n, m, k;
int x, y, z;
int s[K], e[K];
int p[K << 2];
map<int, int>id;
ll dis[K << 2][K << 2];
int cnt;
int vis[N];
ll d[N];
struct Node {
long long d;
int u;
bool operator < (const Node& rhs)const {
return d > rhs.d;
}
};
priority_queue<Node>Q;
void Dijkstra(int uu) {
for (int i = 0; i <= n; i++) {
d[i] = inf;
vis[i] = 0;
}
d[uu] = 0;
while (!Q.empty())Q.pop();
Q.push(Node{ 0,uu });
while (!Q.empty()) {
Node x = Q.top(); Q.pop();
int u = x.u;
if (vis[u]) {
continue;
}
vis[u] = 1;
for (int i = head[u]; i; i = E[i].next) {
Edge e = E[i];
if (d[e.to] > d[u] + e.w) {
d[e.to] = d[u] + e.w;
Q.push(Node{ d[e.to],e.to });
}
}
}
for (int i = 1; i <= cnt; i++) {
dis[id[uu]][id[p[i]]] = d[p[i]];
}
}
ll dp[19][1 << 19];
signed main() {
scanf("%lld%lld%lld", &n, &m, &k);
for (int i = 1; i <= m; i++) {
scanf("%lld%lld%lld", &x, &y, &z);
addEdge(x, y, z);
addEdge(y, x, z);
}
cnt = 0;
for (int i = 1; i <= k; i++) {
scanf("%lld%lld", s + i, e + i);
p[++cnt] = s[i];
p[++cnt] = e[i];
}
sort(p + 1, p + 1 + cnt);
cnt = unique(p + 1, p + 1 + cnt) - p - 1;
for (int i = 1; i <= cnt; i++) {
id[p[i]] = i;
}
for (int i = 1; i <= cnt; i++) {
Dijkstra(p[i]);
}
memset(dp, 0x3f, sizeof dp);
for (int i = 1; i <= k; i++) {
dp[i][1 << (i - 1)] = dis[id[s[i]]][id[e[i]]];
}
for (int i = 0; i < (1 << k); i++) {
for (int j = 1; j <= k; j++) {
if (i & (1 << (j - 1)))continue;
for (int x = 1; x <= k; x++) {
if ((i & (1 << (x - 1))) == 0)continue;
int ex = id[e[x]];
int sj = id[s[j]];
int ej = id[e[j]];
dp[j][i | (1 << (j - 1))] = min(dp[j][i | (1 << (j - 1))],
dp[x][i] + dis[ex][sj] + dis[sj][ej]);
}
}
}
ll ans = inf;
for (int i = 1; i <= k; i++) {
ans = min(ans, dp[i][(1 << k) - 1]);
}
if (ans == inf)ans = -1;
printf("%lld
", ans);
}
C. ELI'S CURIOUS MIND
OEIS 过的,待补
题意是说不可继续扩展的最长不含相邻元素的子序列的个数
已补
其实也很简单,根本不需要打表
$ x_{i-3},x_{i-2},x_{i-1},x_i$ 考虑以 (x_i) 结尾,则只能由 (x_{i-3}) 跟 (x_{i-2}) 转移过来
L = [0,0,0,1,3,4]
ans = [1,1,2,2,3]
for i in range(100):
ans.append(ans[-3] + ans[-2])
cnt = 0
while True:
cnt += 1
n = int(input())
if n == 0:
break
if n < 4:
print("Case #"+str(cnt)+":",L[n])
else:
print("Case #"+str(cnt)+":",ans[n])
D. EXPLORACE
MST, 队友写的
待补
E. MATRIX MULTIPLICATION CALCULATOR
模拟矩阵运算,队友做的
待补
F. SUM OF SUB RECTANGLE AREAS
又是 OEISx
已补
其实也很简单
枚举矩形的长宽
[sum_{a=1}^Nsum_{b=1}^N[N-a+1]*[N-b+1]a*b \= sum_{a=1}^N[N-a+1]*asum_{b=1}^N[N-b+1]*b\= (sum_{i=1}^N[N-i+1]*i)^2\=sum_{i=1}^N(N+1)*i - sum_{i=1}^Ni^2 \= (N+1)*dfrac{N*(N+1)}2 - dfrac{(2*N+1)*N*(N+1)}6
]
def f(n):
return (n+1)*n*(n+1)//2 - (n+1)*n*(2*n+1)//6
for _ in range(int(input())):
n = int(input())
print(f(n)*f(n))
G. WAK SANI SATAY
水题
a = 0.8 - 15.5/85
b = 1.0 - 32 / 85
c = 1.2 - 40 / 85
d = 0.8 - 0.2
cnt = 0
while True:
cnt += 1
n = int(input())
if n == 0:
break
ans = 0
for _ in range(n):
A,B,C,D = map(int,input().split())
ans += A*a+B*b+C*c+D*d
print("Case #%d: RM%.2f"%(cnt,ans))
H. STROOP EFFECT
阅读题
for _ in range(int(input())):
M = [[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0]]
L = input().split()
n = len(L) - 1
u = 0
ok = True
for i in range(1,n-1):
if (L[i][0] == L[i-1][0] and L[i][0] == L[i+1][0]) or (L[i][1] == L[i-1][1] and L[i][1] == L[i+1][1]):
ok = False
for i in L:
if i == "00":
break
if i[0] == i[1]:
u += 1
a = int(i[0]) - 1
b = int(i[1]) - 1
M[a][b] += 1
#for i in M:
# print(*i)
if u*2 != n or M[0][0]%3 != 0 or not ok:
print("Case #%d: Not Stroop"%(_+1))
else:
ok = True
x = M[0][0]//3
for i in range(4):
for j in range(i):
if(M[i][j]!=M[j][i] or M[i][j]+M[j][i] != x*2):
ok = False
if ok:
print("Case #%d: Stroop"%(_+1))
else:
print("Case #%d: Not Stroop"%(_+1))
I. SUPER BALL
简单 DP
//dp[i][j]
#include<bits/stdc++.h>
using namespace std;
const int N = 5e2 + 10;
int dp[N][N];
int cost[N][N];
int G[N][N];
int re[N][N];
int Lay[N];
int n, f;
int main() {
scanf("%d%d", &n, &f);
memset(re, 0x3f, sizeof re);
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
scanf("%d", &G[i][j]);
}
for (int j = 1; j <= f; j++) {
scanf("%d", &cost[i][j]);
if (cost[i][j] == -1)cost[i][j] = 0x3f3f3f3f;
}
for (int j = 1; j <= f; j++) {
scanf("%d", &re[i][j]);
if (re[i][j] == -1)re[i][j] = 0x3f3f3f3f;
}
}
int k; scanf("%d", &k);
for (int i = 1; i <= k; i++) {
scanf("%d", Lay + i);
}
memset(dp, 0x3f, sizeof dp);
for (int i = 1; i <= n; i++) {
dp[1][i] = cost[i][Lay[1]];
}
for (int i = 2; i <= k; i++) {
for (int j = 1; j <= n; j++) {
for (int k = 1; k <= n; k++) {
dp[i][j] = min(dp[i][j], dp[i - 1][k] + G[k][j] + cost[j][Lay[i]]);
}
}
}
int ans = 0x3f3f3f3f;
for (int i = 1; i <= n; i++) {
ans = min(ans, dp[k][i]);
}
memset(dp, 0x3f, sizeof dp);
for (int i = 1; i <= n; i++) {
dp[k][i] = re[i][Lay[k]];
}
for (int i = k - 1; i >= 1; i--) {
for (int j = 1; j <= n; j++) {
for (int kk = 1; kk <= n; kk++) {
dp[i][j] = min(dp[i][j], dp[i + 1][kk] + G[kk][j] + re[j][Lay[i]]);
}
}
}
int res = 0x3f3f3f3f;
for (int i = 1; i <= n; i++) {
res = min(res, dp[1][i]);
}
printf("%d
", ans + res);
}
J. VIRUS OUTBREAK
大数斐波那契
f = []
f.append(0)
f.append(1)
for i in range(600):
f.append(f[-1] + f[-2])
while True:
n = int(input())
if n == -1:
break
print("Hour: " + str(n) + ": " + str(f[n]) + " cow(s) affected")