BestCoder Round #36 HDU(5198 - 5201)

人生第一次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_pair


char 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_pair


int 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 1000000007

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


基于html+python+Apriori 算法、SVD(奇异值分解)的电影推荐算法+源码+项目文档+算法解析+数据集,适合毕业设计、课程设计、项目开发。项目源码已经过严格测试,可以放心参考并在此基础上延申使用,详情见md文档 电影推荐算法:Apriori 算法、SVD(奇异值分解)推荐算法 电影、用户可视化 电影、用户管理 数据统计 SVD 推荐 根据电影打分进行推荐 使用 svd 模型计算用户对未评分的电影打分,返回前 n 个打分最高的电影作为推荐结果 n = 30 for now 使用相似电影进行推荐 根据用户最喜欢的前 K 部电影,分别计算这 K 部电影的相似电影 n 部,返回 K*n 部电影进行推荐 K = 10 and n = 5 for now 根据相似用户进行推荐 获取相似用户 K 个,分别取这 K 个用户的最喜爱电影 n 部,返回 K*n 部电影进行推荐 K = 10 and n = 5 for now Redis 使用 Redis 做页面访问次数统计 缓存相似电影 在使用相似电影推荐的方式时,每次请求大概需要 6.6s(需要遍历计算与所有电影的相似度)。 将相似电影存储至 redis 中(仅存储 movie_id,拿到 movie_id 后还是从 mysql 中获取电影详细信息), 时间缩短至:93ms。 十部电影,每部存 top 5 similar movie 登录了 1-6 user并使用了推荐系统,redis 中新增了 50 部电影的 similar movie,也就是说,系统只为 6 为用户计算了共 60 部电影的相似度,其中就有10 部重复电影。 热点电影重复度还是比较高的
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值