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

原文地址:https://www.cnblogs.com/cniwoq/p/7348188.html