2019暑假多校训练第二场 | 部分题解

这次没有爆零

有点感动

题解链接:https://pan.baidu.com/s/1b9i0yI1oEDcaCZc_SH-K3Q 提取码: k2xc 复制这段内容后打开百度网盘手机App,操作更方便哦

10 Just Skip The Problem 

HDU 6600 考虑二进制

题目大意:有一个数x 在范围0~ (2^n)-1 内

询问 一个数 y 给出答案 x & y==y 

可以询问多次 询问之后 一起给出回答

可以简单证明得到 

范围是 0~(2^n)-1时 需要n个数得到最小的方案数 

因为两个方案的询问次序不同可算作两种方案 

所以 答案是 n !

PS:当n>1000003 时 乘积已经可以整除1000003了 得到0

举个栗子:

#include <stdio.h>
#include <string.h>
#include <iostream>
#include <math.h>
#include <bits/stdc++.h>
using namespace std;
#define ll long long
int const mod = 1e6 + 3;
ll a[1000005];
int main()
{
    int n;
    ll  ans = 1;
    for (int i = 1; i < 1000005; i++) {
        ans = (ans * i) % mod;
        a[i] = ans;
    }
    while (~scanf("%d", &n)) {
        if (n >= mod) {
            printf("0\n");
        } else {
            printf("%lld\n", a[n]);
        }
    }
    return 0;
}

 

05 Everything Is Generated In Equal Probability 

HDU 6595 找规律 + 求逆元

\frac{1}{3}=\frac{3}{9}

\frac{8}{9}

\frac{2}{3}+1=\frac{ 5}{3}=\frac{15}{9}

所以分子是 3 8 15 24……

分母是9

(不是我推的 我好菜啊TAT)

然后求逆元emmm

#include <stdio.h>
#include <string.h>
#include <iostream>
#include <math.h>
#include <bits/stdc++.h>
using namespace std;
#define ll long long
ll const mod = 998244353;
ll quickpow(ll x, ll n)
{
    int res = x;
    int ans = 1;
    while (n) {
        if (n & 1) {
            ans = (ans % mod * (res % mod)) % mod ;
        }
        res = (res % mod * (res % mod)) % mod ;
        n = n >> 1;
    }
    return ans;
}
int main()
{
    int n;
    while (~scanf("%d", &n)) {
        ll t = 3;
        ll ans = 0;
        for (int i = 1; i < n; i++) {
            ans += t;
            t = t + 2;
        }
        //  printf("%lld\n", quickpow(9,mod-2)%mod);
        printf("%lld\n", (ans * quickpow(9, mod - 2)) % mod);
    }

    return 0;
}

 

11 Keen On Everything But Triangle

HDU 6601 主席树+ 斐波那契前44个

参考:https://www.cnblogs.com/Chen-Jr/p/11240189.html

 

用了bin巨的模板 但是 这是找主席树第K小的

所以在最后算三角形周长的时候需要 变换一下

找最大的能组成三角形的三个数

#include <stdio.h>
#include <math.h>
#include <bits/stdc++.h>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define ll long long
const int maxn = 100010;
const int M = maxn * 30;
int q, n, m, tot;
int a[maxn], t[maxn];
int T[maxn], lson[M], rson[M], c[M];
void Init_hash()//将数组复制到另一个数组 并排序去重
{
    for (int i = 1; i <= n; i++) {
        t[i] = a[i];
    }
    sort(t + 1, t + 1 + n);
    m = unique(t + 1, t + 1 + n) - t - 1;
}
int build(int l, int r)//建树
{
    int root = tot++;
    c[root] = 0;
    if (l != r) {
        int mid = (l + r) >> 1;
        lson[root] = build(l, mid);
        rson[root] = build(mid + 1, r);
    }
    return root;
}
int Hash(int x)//快速找到x的位置
{
    return lower_bound(t + 1, t + 1 + m, x) - t;
}
int update(int root, int pos, int val)//更新节点
{
    int newroot = tot++, tmp = newroot;
    c[newroot] = c[root] + val;
    int l = 1, r = m;
    while (l < r) {
        int mid = (l + r) >> 1;
        if (pos <= mid) {
            lson[newroot] = tot++;
            rson[newroot] = rson[root];
            newroot = lson[newroot];
            root = lson[root];
            r = mid;
        } else {
            rson[newroot] = tot++;
            lson[newroot] = lson[root];
            newroot = rson[newroot];
            root = rson[root];
            l = mid + 1;
        }
        c[newroot] = c[root] + val;
    }
    return tmp;
}
int query(int left_root, int right_root, int k)//查询l ~r中第k小的
{
    int l = 1, r = m;
    while (l < r) {
        int mid = (l + r) >> 1;
        if (c[lson[left_root]] - c[lson[right_root]] >= k) {
            r = mid;
            left_root = lson[left_root];
            right_root = lson[right_root];

        } else {
            l = mid + 1;
            k -= c[lson[left_root]] - c[lson[right_root]];
            left_root = rson[left_root];
            right_root = rson[right_root];
        }
    }
    return l;
}
int main()
{
    while (~scanf("%d%d", &n, &q)) {
        tot = 0;
        for (int i = 1; i <= n; i++) {
            scanf("%d", &a[i]);
        }
        Init_hash();
        T[n + 1] = build(1, m);
        for (int i = n; i > 0; i--) {
            int pos = Hash(a[i]);
            T[i] = update(T[i + 1], pos, 1);
        }
        while (q--) {
            int l, r, k;
            scanf("%d%d", &l, &r);
            int m = r - l + 1;
            ll ans = -1;
            while (m >= 3) {
                int a = t[query(T[l], T[r + 1], m)];
                int b = t[query(T[l], T[r + 1], m - 1)];
                int c = t[query(T[l], T[r + 1], m - 2)];
                if (b + c > a) {
                    ans = 1ll * a + 1ll * b + 1ll * c ;
                    break;
                }
                m--;
            }
            printf("%lld\n", ans);
        }
    }
    return 0;
}

12 Longest Subarray

HDU 6602 线段树

题目大意:给 n 个数字,这串数字中范围是1~c,合法条件是某一段区间内出现任何一个数字,它出现的次数>=k或者=0

求合法条件下的最长连续子序列的长度是多少?

 

 

09 I Love Palindrome String 

HDU 6599 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值