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