The Preliminary Contest for ICPC Asia Shanghai 2019

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;
}

  

 

posted @ 2019-09-15 18:24  Snow_in_winer  阅读(524)  评论(0编辑  收藏  举报