Loading

2020牛客国庆集训派对day2

在队友的带领下,第一次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\n", 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\n", 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}^N\sum_{b=1}^N[N-a+1]*[N-b+1]a*b \\= \sum_{a=1}^N[N-a+1]*a\sum_{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\n", 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")
posted @ 2020-10-03 09:58  —O0oO-  阅读(217)  评论(0编辑  收藏  举报