BestCoder Round #36 HDU(5198 - 5201)

来源:互联网 发布:课程录制软件 编辑:程序博客网 时间:2024/05/20 20:18

人生第一次ak了bc, 当然要写个题解装逼一下。。(其实是题水。。。)


Hdu 5198 Strang Class

水题。。 不过wa了两发。。
#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>#include <cmath>#include <queue>#include <vector>#include <set>#include <map>using namespace std;#define mxn 100020#define LL long long#define inf 0x3f3f3f3f#define MP make_pairchar s[mxn];int n;bool check(int l, int r) {    for(int i = l; i <= r; ++i)        if(s[i] != s[l]) return 0;    return 1;}int main() {    while(scanf("%s", s + 1) != EOF) {        n = strlen(s + 1);        if(n % 3 != 0) {            puts("NO");            continue;        }        int x = n / 3 + 1;        int y = n / 3 * 2 + 1;        int z = n / 3;        if(check(1, 1 + z - 1) && check(x, x + z - 1) && check(y, y + z - 1)) {            if(s[1] != s[x] && s[1] != s[y] && s[x] != s[y])                puts("YES");            else                puts("NO");        }        else            puts("NO");    }    return 0;}


Hdu 5199 Gunner

也是水题, 离散化一下, 再加个输入挂就ok了
#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>#include <cmath>#include <queue>#include <vector>#include <set>#include <map>using namespace std;#define mxn 1000200#define LL long long#define inf 0x3f3f3f3f#define MP make_pairint n, m;int a[mxn];int readint() {    char c;    while((c = getchar()) && !(c >= '0' && c <= '9'));    int ret = c - '0';    while((c = getchar()) && (c >= '0' && c <= '9'))        ret = ret * 10 + c - '0';    return ret;}int san[mxn], cnt;bool vis[mxn];int f(int v) {    int k = lower_bound(a + 1, a + n + 1, v) - a;    if(k > n || a[k] != v)        return 0;    return 1;}int main() {    while(scanf("%d%d", &n, &m) != EOF) {        for(int i = 1; i <= n; ++i) a[i] = readint();        memset(vis, 0, sizeof vis);        sort(a + 1, a + n + 1);        while(m--) {            int v;            v = readint();            if(f(v) == 0) {                puts("0");                continue;            }            int p = lower_bound(a + 1, a + n + 1, v) - a;            if(vis[p]) {                puts("0");                continue;            }            else {                int y = upper_bound(a + 1, a + n + 1, v) - a;                vis[p] = 1;                printf("%d\n", y - p);            }        }    }    return 0;}

Hdu 5200 Trees

题意:
给n个数, 树高为hi, q次询问, 每次询问把小于等于v的树都去掉, 剩下的树分成了几块。
思路:
正向处理的话用线段树是比较麻烦的, 但是如果离线的话, 按照询问从小到达来处理就比较容易。
把一个树去掉的话, 如果它的旁边没有树的话, 分块数要减少1, 如果有两棵树的话, 分块数加1, 否则不变。
#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>#include <cmath>#include <queue>#include <vector>#include <set>#include <map>using namespace std;#define mxn 50020#define LL long long#define inf 0x3f3f3f3f#define MP make_pair#define ls (i << 1)#define rs (ls | 1)#define md ((ll + rr) >> 1)struct query {    int x, id, ans;    bool operator < (const query &b) const {        return x < b.x;    }}s[mxn];bool cmp(query a, query b) {    return a.id < b.id;}int n, q;struct node {    int h, p;    bool operator < (const node &b) const {        return h < b.h;    }}a[mxn];bool c[mxn];int main() {    while(scanf("%d%d", &n, &q) != EOF) {        for(int i = 1; i <= n; ++i) {            scanf("%d", &a[i].h);            a[i].p = i;        }        sort(a + 1, a + n + 1);        for(int i = 1; i <= q; ++i) {            scanf("%d", &s[i].x);            s[i].id = i;        }        sort(s + 1, s + q + 1);        int ans = 1;        memset(c, true, sizeof c);        int j = 1;        for(int i = 1; i <= q; ++i) {            while(j <= n && a[j].h <= s[i].x) {                int h = a[j].p;                int cnt = 0;                if(h > 1 && c[h-1]) ++cnt;                if(h < n && c[h+1]) ++cnt;                if(cnt == 2) ++ans;                else if(cnt == 0) --ans;                c[h] = 0;                ++j;            }            s[i].ans = ans;        }        sort(s + 1, s + q + 1, cmp);        for(int i = 1; i <= q; ++i)            printf("%d\n", s[i].ans);    }    return 0;}

Hdu 5201 The Monkey King

题意:
要把n个桃子分给m个猴子, 其中第一个猴子的桃子要严格最多的, 问方案数。
思路:
可以枚举分多少个桃子给第一个猴子, 假设为x, 那么分给其他猴子的桃子假设为a[i], 那么
a[2] + a[3] + ... + a[m-1] = n - x, 如果没有限制的话, 答案就是f(n-x, m-1), f(x, y) 表示把x个桃子分给y个猴子的方案,显然f(x, y) = C(x + y - 1, x), C是组合数。
有限制的话, 可以根据容斥, 算出总的,然后减去1个猴子比第一个猴子的桃子多的方案,然后加上2个猴子比第一个猴子多的方案。。。
k个猴子比第一个猴子多的方案是C(m-1, k) * f(n - (k + 1) * x, m - 1)。
然后加起来就可以了。
刚开始sb了, 以为这么算复杂度是n^2。
其实每个x, 都是只有O(n/x)次计算的, 因为n - (k + 1) * x < 0时候就跳出循环, 所以复杂度和筛法那样。
#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>#include <cmath>#include <queue>#include <vector>#include <set>#include <map>using namespace std;#define mxn 200020#define LL long long#define inf 0x3f3f3f3f#define MP make_pair#define ls (i << 1)#define rs (ls | 1)#define md ((ll + rr) >> 1)#define mod 1000000007LL fac[mxn], nfac[mxn];LL qpow(LL x, int k) {    LL ret = 1;    while(k) {        if(k & 1) ret = ret * x % mod;        x = x * x % mod;        k >>= 1;    }    return ret;}void init() {    fac[0] = fac[1] = nfac[0] = nfac[1] = 1;    for(int i = 2; i < mxn; ++i) {        fac[i] = fac[i-1] * i % mod;        nfac[i] = qpow(fac[i], mod - 2);    }}int n, m;LL C(int x, int y) {    if(y < 0 || y > x) return 0;    return fac[x] * nfac[y] % mod * nfac[x-y] % mod;}LL f(int r, int k) {    return C(r + k - 1, r);}LL calc(LL x) {    LL ret = 0;    for(int k = 0; (k + 1) * x <= n; ++k) {        LL t = C(m - 1, k) * f(n - (k + 1) * x, m - 1) % mod;        if(k & 1)            ret = ((ret - t) % mod + mod) % mod;        else            ret = (ret + t) % mod;    }    return ret;}int main() {    init();    int cas;    scanf("%d", &cas);    while(cas--) {        scanf("%d%d", &n, &m);        if(m == 1) {            printf("%d\n", 1);            continue;        }        int t = n / m;        if(n % m == 0) ++t;        else if(n % m != 1) t += 2;        LL ans = 0;        for(int i = max(1, t); i <= n; ++i) {            ans = (ans + calc(i)) % mod;        }        printf("%I64d\n", ans);    }    return 0;}


0 0
原创粉丝点击