The Preliminary Contest for ICPC Asia Shanghai 2019
Light bulbs
题意:有n盏灯,初始都是灭的状态,p次操作,每次操作翻转a到b盏灯的状态,问最终操作完成后几盏灯是亮着的。
思路:内存限制8192K,显然不能用线段树,只能用数组操作,但是也不能直接遍历1e6的数组,所以我们用map标记头和尾,最后只遍历所存的点就好,将头每次加1,尾后面的点每次减1,对于每次操作,只有奇数次才能操作。具体看代码。
#include <bits/stdc++.h> using namespace std; map<int,int>mp; map<int,int>::iterator it; int n,m; int main() { int _,ca=0; scanf("%d", &_); while (_--) { scanf("%d%d", &n, &m); for (int i = 1, a, b; i <= m; i++) { scanf("%d%d", &a, &b); mp[a]++; mp[b + 1]--; } int ans=0,sum = 0,last=0; for (it = mp.begin(); it != mp.end(); it++) { if (sum % 2 == 1) { ans += it->first - last; } last = it->first; sum += it->second; } mp.clear(); printf("Case #%d: %d ",++ca,ans); } return 0; }
Peekaboo
https://www.luogu.org/problemnew/solution/P2508
Stone game
题意:
给你n个只有重量的石头,让你取出一些石头,记这个重量为s1(其中最轻的石头的重量为t),剩下石头的重量为s2,问你有多少种情况使得s1>=s2&&s1-t<=s2.
题解:
虽然这道题非常简单啊,但是先写一下,因为需要一道水题记录一下退背包这种算法。
其实他好像可以从大到小做的,但是我并不想就是要退
从小到大枚举石头的重量,然后先退掉每一个重量,然后再for一遍可行的区间:
max((s+1)/2−a[i],0) 因为我们退掉了a[i]的重量,所以左端点就是这个值,然后右端点,由与我们枚举的是j,但是我们已经减掉了a[i],所以它其实是a[i]+j,不等式是这样的:(j+a[i])−a[i]<=s−(j+a[i])
for一遍即可。
#include <bits/stdc++.h> using namespace std; typedef long long ll; const ll mod=1e9+7; const ll inf=0x3f3f3f3f3f3f3f3f; ll dp[310*500+5]; int a[310]; int main() { int _; scanf("%d", &_); while (_--) { int n, sum = 0; scanf("%d", &n); for (int i = 1; i <= n; i++) { scanf("%d", &a[i]); sum += a[i]; } sort(a + 1, a + n + 1); for (int i = 0; i <= sum; i++) dp[i] = 0; dp[0] = 1; for (int i = 1; i <= n; i++) { for (int j = sum; j >= a[i]; j--) { dp[j] = (dp[j] + dp[j - a[i]]) % mod; } } ll ans = 0; for (int i = 1; i <= n; i++) { for (int j = a[i]; j <= sum; j++) { dp[j] = (dp[j] - dp[j - a[i]] + mod) % mod; } for (int j = max((sum + 1) / 2 - a[i], 0); j <= sum - j - a[i]; j++) { ans = (ans + dp[j]) % mod; } } printf("%lld ", ans); } return 0; }
Lightning Routing I
Counting Sequences I
#include <bits/stdc++.h> using namespace std; const int maxn=3010; typedef long long ll; const ll mod=1e9+7; ll fac[maxn],inv[maxn],ans[maxn]; ll C(int n,int m) { return fac[n] * inv[m] % mod * inv[n - m] % mod; } ll pow_mod(ll a,ll b) { ll res = 1; while (b) { if (b & 1) { res = res * a % mod; } b >>= 1; a = a * a % mod; } return res; } bool vis[maxn]; int Q[maxn]; ll deal(int n,int one) { if (n == 0) return 1; unordered_map<int, int> ma; for (int i = 1; i <= n; i++) { ma[Q[i]]++; } ll ans = fac[n + one] * inv[one] % mod; for (auto it:ma) { ans = ans * inv[it.second] % mod; } return ans; } void dfs(int num,int sum,int mul) { if (vis[mul - sum + num]) { ans[mul - sum + num] = (ans[mul - sum + num] + deal(num, mul - sum)) % mod; } for (int i = max(2, Q[num]); i <= 6000; i++) { if (mul * i - (sum + i) + num + 1 > 3000) break; Q[num + 1] = i; dfs(num + 1, sum + i, mul * i); } } int q[maxn]; int main() { fac[0] = 1; for (int i = 1; i < maxn; i++) fac[i] = fac[i - 1] * i % mod; inv[maxn - 1] = pow_mod(fac[maxn - 1], mod - 2); for (int i = maxn - 2; i >= 0; i--) { inv[i] = inv[i + 1] * (i + 1) % mod; } int t; scanf("%d", &t); for (int i = 1; i <= t; i++) { scanf("%d", &q[i]); vis[q[i]] = 1; } dfs(0, 0, 1); for (int i = 1; i <= t; i++) { printf("%lld ", ans[q[i]]); } return 0; }