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\n",++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\n", 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\n", ans[q[i]]);
}
return 0;
}