2017 Multi-University Training Contest

来源:互联网 发布:华星创业网络报销网址 编辑:程序博客网 时间:2024/06/06 07:53

1003

题意:d(i)为i的因子的个数,求区间[l, r] 所有d(i)     l<=i <=r  的和

因子个数求法:传送门

思路:这样直接去求还是会TLE,所以我们用类似素数筛法进行区间筛来减少计算次数

每次在区间内找到第一个能整除素数p的,假设这个数是x,那么x + p 也是可以整除p的。就是普通的线性筛类似

#include <cstdio>#include <cstring>#include <cmath>#include <sstream>#include <iostream>#include <algorithm>#include <string>#include <stack>#include <queue>#include <vector>#include <map>#include <set>#include <utility>using namespace std;#define LL long long#define pb push_back#define mk make_pair#define pill pair<int, int>#define ft first#define sd second#define mst(a, b)    memset(a, b, sizeof a)#define REP(i, x, n)    for(int i = x; i <= n; ++i)const int qq = 5e6 + 10;const LL MOD = 998244353;LL prime[qq], tot = 0;bool ispirme[qq];LL l, r, k;LL num[qq], ans[qq];void Init() {    for(int i = 2; i < qq; ++i) {        if(!ispirme[i]) {            prime[++tot] = i;        }        for(int j = 1; j <= tot && (LL)i * prime[j] < qq; ++j) {            ispirme[(LL)i * prime[j]] = true;            if(i % prime[j] == 0)    break;        }    }//    printf("QQQ\n");}int main(){    Init();    int t;    scanf("%d", &t);    while(t--) {        scanf("%lld%lld%lld", &l, &r, &k);        for(LL i = l; i <= r; ++i) {            num[i - l] = i;            ans[i - l] = 1;        }//        printf("QQQ\n");        for(LL i = 1; i <= tot; ++i) {            LL j = (l + prime[i] - 1LL) / prime[i] * prime[i];//            printf("%lld\n", j);//            if(r < prime[i])    break;            while(j <= r) {                LL p = 0;                while(num[j - l] % prime[i] == 0) {                    p++;                    num[j - l] /= prime[i];                }                ans[j - l] = (ans[j - l] * (p * k + 1LL));                if(ans[j - l] >= MOD)    ans[j - l] %= MOD;                j = j + prime[i];//                printf("%lld\n", j);            }        }        LL sum = 0;        for(LL i = l; i <= r; ++i) {            if(num[i - l] != 1)    sum = sum + ans[i - l] * (k + 1LL);            else    sum = sum + ans[i - l];            if(sum >= MOD)    sum %= MOD;        }        printf("%lld\n", sum);    }    return 0;}



1007

题意:给定二分图,求出图中所有完全匹配图的边权乘积的和,保证至少有一种完全匹配

思路:参考这位聚聚的代码 传送门

e[i] = e[i ^ 1] = 1 是标记了边。之前在想标记点为什么不行后来比对了两份标记边和点的代码发现

标记点访问顺序:8 16 9 18

标记边的访问顺序:8 16 9 18 8

感觉做一下处理标记点也是可以的,不过好像比较麻烦

#include <cstdio>#include <cstring>#include <cmath>#include <sstream>#include <iostream>#include <algorithm>#include <string>#include <stack>#include <queue>#include <vector>#include <map>#include <set>#include <utility>using namespace std;#define LL long long#define pb push_back#define mk make_pair#define pill pair<int, int>#define ft first#define sd second#define mst(a, b)memset(a, b, sizeof a)#define REP(i, x, n)for(int i = x; i <= n; ++i)const int qq = 300000 + 10;const int MOD = 998244353;struct Edge {int nxt, to, w;bool mrk;}e[qq << 2];int T, n, head[qq << 1], cnt, deg[qq << 1], used[qq << 1];LL part[2];void Init() {mst(head, -1);mst(deg, 0);mst(used, 0);cnt = 0;}void AddEdge(int u, int v, int w) {e[cnt].nxt = head[u];e[cnt].to = v;e[cnt].w = w;e[cnt].mrk = 0;head[u] = cnt++;}void Dfs(int cur, int idx) {printf("%d ", cur);used[cur] = 1;for(int i = head[cur]; i != -1; i = e[i].nxt) {if(e[i].mrk)continue;e[i].mrk = e[i ^ 1].mrk = 1;(part[idx] *= e[i].w) %= MOD;Dfs(e[i].to, 1 - idx);}}int main(){scanf("%d", &T);while(T--) {scanf("%d", &n);Init();for(int u = 1, v, w; u <= n; ++u) {for(int j = 0; j < 2; ++j) {scanf("%d%d", &v, &w);AddEdge(u, v + n, w);AddEdge(v + n, u, w);deg[u]++, deg[v + n]++;}}LL ans = 1;queue<int> Q;for(int v = n + 1; v <= n + n; ++v) {if(deg[v] == 1) {Q.push(v);}}while(!Q.empty()) {int v = Q.front();Q.pop();used[v] = 1;for(int i = head[v]; i != -1; i = e[i].nxt) {if(e[i].mrk)continue;e[i].mrk = e[i ^ 1].mrk = 1;used[e[i].to] = 1;(ans *= e[i].w) %= MOD;for(int j = head[e[i].to]; j != -1; j = e[j].nxt) {e[j].mrk = e[j ^ 1].mrk = 1;deg[e[j].to]--;if(deg[e[j].to] == 1)Q.push(e[j].to);}}}printf("%lld\n", ans);for(int u = 1; u <= n; ++u) {if(used[u])continue;part[0] = part[1] = 1;Dfs(u, 0);puts("");printf("%lld %lld\n", part[0], part[1]);(ans *= (part[0] + part[1]) % MOD) %= MOD;}printf("%lld\n", ans);}return 0;}




1009

题意:给出n个数字,要你求m k,要求给出的n个数%m = k 的数字的个数要大于一半

思路:固定m = 2, 那么k只有两种情况0和1统计下等于1和等于0的情况,谁多k就是那个

#include <cstdio>#include <cstring>#include <cmath>#include <sstream>#include <iostream>#include <algorithm>#include <string>#include <stack>#include <queue>#include <vector>#include <map>#include <set>#include <utility>using namespace std;#define LL long long#define pb push_back#define mk make_pair#define pill pair<int, int>#define ft first#define sd second#define mst(a, b)    memset(a, b, sizeof a)#define REP(i, x, n)    for(int i = x; i <= n; ++i)const int qq = 1e5 + 10;const int MOD = 1e9 + 7;int num[qq];int main(){    int t;    scanf("%d", &t);    while(t--) {        int n;    scanf("%d", &n);        int a, b;        a = b = 0;        for(int x, i = 0; i < n; ++i) {            scanf("%d", &x);            if(x % 2 == 0)    a++;            else    b++;        }        if(a > b)    puts("2 0");        else    puts("2 1");    }    return 0;}





1011

题意:给出图像要你判断时间是多少

思路:观察每个数字缺少那一块,标记那一块,然后做一下判断

#include <cstdio>#include <cstring>#include <cmath>#include <sstream>#include <iostream>#include <algorithm>#include <string>#include <stack>#include <queue>#include <vector>#include <map>#include <set>#include <utility>using namespace std;#define LL long long#define pb push_back#define mk make_pair#define pill pair<int, int>#define ft first#define sd second#define mst(a, b)    memset(a, b, sizeof a)#define REP(i, x, n)    for(int i = x; i <= n; ++i)const int qq = 1e5 + 10;const int MOD = 1e9 + 7;char st[10][105], match[10][10];bool digit[10];int num[10][10];int ans[10];void Init() {    mst(num, 0);    num[0][4] = 1;    num[1][1] = num[1][2] = num[1][4] = num[1][5] = num[1][7] = 1;    num[2][2] = num[2][6] = 1;    num[3][2] = num[3][5] = 1;    num[4][1] = num[4][5] = num[4][7] = 1;    num[5][3] = num[5][5] = 1;    num[6][3] = 1;    num[7][2] = num[7][4] = num[7][5] = num[7][7] = 1;    num[9][5] = 1;}void Judge(int id) {    for(int i = 0; i < 10; ++i)    digit[i] = false;    if(match[1][2] == 'X' && match[1][3] == 'X') {        digit[1] = true;    }    if(match[2][1] == 'X' && match[3][1] == 'X') {        digit[2] = true;    }    if(match[2][4] == 'X' && match[3][4] == 'X') {        digit[3] = true;    }    if(match[4][2] == 'X' && match[4][3] == 'X') {        digit[4] = true;    }    if(match[5][1] == 'X' && match[6][1] == 'X') {        digit[5] = true;    }    if(match[5][4] == 'X' && match[6][4] == 'X') {        digit[6] = true;    }    if(match[7][2] == 'X' && match[7][3] == 'X') {        digit[7] = true;    }    for(int i = 0; i < 10; ++i) {        bool f = true;        for(int j = 1; j <= 7; ++j) {            int a = num[i][j];            int b = (digit[j] == true ? 0 : 1);            if(a != b)    f = false;        }        if(f){            ans[id] = i;            break;        }    }    } int main(){    int t;    scanf("%d", &t);    Init();    while(t--) {        for(int i = 1; i <= 7; ++i) {            scanf("%s", st[i] + 1);        }        int x, y;        x = y = 0;        for(int i = 1; i <= 7; ++i) {            ++x;            y = 0;            for(int j = 1; j <= 4; ++j) {                ++y;                match[x][y] = st[i][j];            }        }        Judge(1);        x = y = 0;        for(int i = 1; i <= 7; ++i) {            ++x;            y = 0;            for(int j = 6; j <= 9; ++j) {                ++y;                match[x][y] = st[i][j];            }        }        Judge(2);        x = y = 0;        for(int i = 1; i <= 7; ++i) {            ++x;            y = 0;            for(int j = 13; j <= 17; ++j) {                ++y;                match[x][y] = st[i][j];            }        }        Judge(3);        x = y = 0;        for(int i = 1; i <= 7; ++i) {            ++x;            y = 0;            for(int j = 18; j <= 21; ++j) {                ++y;                match[x][y] = st[i][j];            }        }        Judge(4);        for(int i = 1; i <= 4; ++i) {            printf("%d", ans[i]);            if(i == 2)    printf(":");        }        puts("");    }    return 0;}


原创粉丝点击