• HDU 2017 多校联合Contest 4



    1003Counting Divisors

    题意:

    给定l, r,k, 计算公式$(sum_{i=1}^{r}d(i^k))mod\,998244353$

    思路:

    函数$d(x)$表示x的因子数。利用算数基本定理可以算出函数,而且根据公式可以知道$i^k$可以通过$i$计算。利用筛选素数的方法快速求出。

    #include "bits/stdc++.h"
    using namespace std;
    typedef long long LL;
    const LL mod = 998244353;
    const int MAXN = 1e6 + 10;
    int prime[MAXN];
    bool is_prime[MAXN];
    LL pos[MAXN], c[MAXN];
    LL l, r, k;
    int p = 0;
    int init() {
        for (int i = 0; i < MAXN; i++) is_prime[i] = true;
        is_prime[0] = is_prime[1] = false;
        for (int i = 2; i < MAXN; i++) {
            if (is_prime[i]) {
                prime[p++] = i;
                for (int j = 2*i; j < MAXN; j += i) is_prime[j] = false;
             }
        }
    }
    void init2() {
        memset(pos, 0, sizeof(pos));
        for (LL i = 0; i <= r-l; i++) pos[i] = l+i, c[i] = 1;
    }
    int main(int argc, char const *argv[])
    {
        init();
        int T; scanf("%d", &T);
        while (T--) {
            LL ans = 0;
            scanf("%lld%lld%lld", &l, &r, &k);
            init2();
            for (int i = 0; i < p; i++) {
                LL t = prime[i];
                LL cur = (l+t-1)/t*t;
                while (cur <= r) {
                    LL cnt = 0;
                    while (pos[cur-l]%t == 0) {pos[cur-l]/=t, cnt++;}
                    c[cur-l] = c[cur-l]*(k*cnt+1)%mod; cur += t;
                }
            }
            for (int i = 0; i <= r-l; i++) {
                if (pos[i] != 1) c[i]=c[i]*(k+1)%mod;
                ans = (ans + c[i])%mod;
            }
            printf("%lld
    ", ans);
        }
        return 0;
    }

    1004 Dirt Ratio

    题意:

    给出一串题目的提交记录,计算''Dirt Ratio''。计算方式是区间的AC数目比上提交的次数。对于每个区间,假设每个题目最后一次出现代表AC。

    思路:

    不会。。。。只能看题解。

    题解的思路是二分mid,计算$frac{size(l,r)}{r-l+1}leq mid$,将公式换成$size(l,r)+mid*lleq mid*(r+1)$。这样对于每个确定的mid和r只有左边的l是变化的。其中size是区间不同的数目

    首先二分mid,枚举r。对于每个mid的检查要靠线段树。

    用一个数组pre记录每个位置上的数上次出现的位置,当枚举r=j的时候,j位置的数要插到区间里的,区间的大小好计算。当j插入到区间的时候,对j出现上次之前到j这段距离的size是有影响的,再靠前的区间有位置j的数出现过,size值不会发生变化,只要更新[pre[j]+1, j]这段区间。然后检查从1~j是否满足公式。建树的时候要赋mid*l的。

    #include "bits/stdc++.h"
    #define lson o<<1, l, mid   
    #define rson o<<1|1, mid+1, r 
    #define ll o<<1         
    #define rr o<<1|1   
    const int maxn = 60000+10;     
    using namespace std;
    int pos[maxn], pre[maxn];
    struct Tree {
        int l, r; 
        double Min;
        int lazy;
    } tree[maxn<<2];
    void push_up(int o){tree[o].Min = min(tree[ll].Min, tree[rr].Min);}
    void push_down(int o) {
        if(tree[o].lazy) {
            tree[ll].lazy += tree[o].lazy;
            tree[rr].lazy += tree[o].lazy;
            tree[ll].Min += tree[o].lazy;
            tree[rr].Min += tree[o].lazy;
            tree[o].lazy = 0;
        }
    } 
    void build_tree(int o, int l, int r, double M) {
        tree[o].l = l, tree[o].r = r;
        tree[o].lazy = 0; 
        if(l == r) {
            tree[o].Min = (double)l*M;
            return;
        }
        int mid = (l+r) >> 1;
        build_tree(lson, M); build_tree(rson, M);
        push_up(o);
    } 
    void update_tree(int o, int L, int R, int val) {
        if(L <= tree[o].l && R >= tree[o].r) {
            tree[o].lazy += val;
            tree[o].Min += val; return;
        }
        push_down(o); 
        int mid = (tree[o].l + tree[o].r) >> 1;
        if(R <= mid) update_tree(ll, L, R, val);
        else if(L > mid) update_tree(rr, L, R, val);
        else {
            update_tree(ll, L, mid, val);
            update_tree(rr, mid+1, R, val);
        }
        push_up(o);
    } 
    double query_tree(int o, int L, int R) {
        if(L <= tree[o].l && R >= tree[o].r) 
            return tree[o].Min;
        push_down(o);
        int mid = (tree[o].l + tree[o].r) >> 1;
        if(R <= mid) return query_tree(ll, L, R);
        if(L > mid) return query_tree(rr, L, R);
        return min(query_tree(ll,L,mid), query_tree(rr, mid+1, R));
    }
    int main()  {  
        int N, T;
        scanf("%d", &T);  
        while(T--)  {
            scanf("%d", &N);
            memset(pos, 0, sizeof(pos));
            for (int i = 1; i <= N; i++) {
                int a;scanf("%d", &a); 
                pre[i] = pos[a]; //位置i上的数上次出现的位置
                pos[a] = i; 
            } 
            double lb = 0, ub = 1.0;
            double res;
            for (int i = 1; i <= 20; i++) {
                double mid = (lb+ub)/2.0;
                build_tree(1, 1, N, mid);
                bool flag = false;
                for (int j = 1; j <= N; j++) {
                    update_tree(1, pre[j]+1, j, 1);
                    double ans = query_tree(1, 1, j);
                    if (ans <= mid*(j+1)) {
                        flag = true; break;
                    }
                }
                if (flag) ub = mid;
                else lb = mid;
                res = mid;
            }
            printf("%.6lf
    ", res);
        }  
        return 0;  
    }

    1009 Questionnaire

    题意:

    给出n个数,求出k和m,使得数组中大于等于一半的数模m后的余数等于k。

    思路:

    直接模2,保证有解。

    #include "bits/stdc++.h"
    using namespace std;
    int main(int argc, char const *argv[])
    {
        int T; scanf("%d", &T);
        while (T--) {
            int odd = 0, eve = 0, a;
            int n; scanf("%d", &n);
            for (int i = 0; i < n; i++) {
                scanf("%d", &a);
                if (a&1) odd++;
                else eve++;
            }
            if (odd > eve) printf("2 1
    ");
            else printf("2 0
    ");
        }
        return 0;
    }

    1011Time To Get Up

    题意:

    给出字符组成的数字时间,把它化成数字。

    思路:

    对每块进行判别。

    #include "bits/stdc++.h"
    using namespace std;
    char s[10][30];
    int sta[7];
    int main(int argc, char const *argv[]) {
        int T; 
        scanf("%d", &T);
        while (T--) {
            getchar();
            for (int i = 0; i < 7; i++) gets(s[i]);
            int i = 0;
            int cnt = 0;
            int pt;
            while (i < 21) {
                memset(sta, 0, sizeof(sta));
                if (s[0][i+1] == 'X') sta[5] = 1;
                if (s[1][i+0] == 'X') sta[0] = 1;
                if (s[4][i+0] == 'X') sta[1] = 1;
                if (s[6][i+1] == 'X') sta[2] = 1;
                if (s[1][i+3] == 'X') sta[4] = 1;
                if (s[4][i+3] == 'X') sta[3] = 1;
                if (s[3][i+1] == 'X') sta[6] = 1;
                if (!sta[6]&&sta[0]&&sta[1]) pt=0;
                else if (!sta[6]&&sta[3]&&sta[4]&&!sta[5])pt=1;
                else if (sta[6]&&sta[1]&&sta[2]&&!sta[3])pt=2;
                else if (sta[6]&&!sta[0]&&sta[3]&&sta[4])pt=3;
                else if (sta[6]&&!sta[5]&&sta[0]&&sta[4])pt=4;
                else if (sta[6]&&sta[0]&&!sta[1]&&sta[3]&&sta[2]&&!sta[4])pt=5;
                else if (sta[6]&&sta[0]&&sta[5]&&!sta[4])pt=6;
                else if (!sta[6])pt=7;
                else if (!sta[1]) pt=9;
                else pt = 8;
                // for (int j = 0; j < 7; j++) printf("%d %d
    ", j, sta[j]);
                printf("%d", pt); 
                i+=5;
                if (i == 10) {i += 2;printf(":");cnt++;}
            }  
            printf("
    ");
        }
        return 0;
    }

  • 相关阅读:
    第二阶段团队冲刺第五天
    第二阶段冲刺七
    第二阶段冲刺六
    第二阶段冲刺五
    第二阶段冲刺四
    冲刺第二阶段三
    冲刺第二阶段二
    冲刺第二阶段 一
    项目总结
    第二阶段SCRUM
  • 原文地址:https://www.cnblogs.com/cniwoq/p/7348188.html
Copyright © 2020-2023  润新知