2017 Multi-University Training Contest

来源:互联网 发布:js dom添加点击事件 编辑:程序博客网 时间:2024/05/29 11:40

HDU - 6097 - Mindis HDU - 6097(圆的反演点)

题意:有一个圆心在原点的圆,给定圆的半径,给定P、Q两点坐标(PO=QO,P、Q不在圆外),取圆上一点D,求PD+QD的最小值。

思路:圆的反演点构造相似三角形。然后数学公式推推推。就有答案了。少个代码。

HDU - 6098 - Inversion(思维)

题意:Bi=maxj%i0Aji2
2n1000001Ai1000000000n700000

思路:将A数组按值从大到小排序,对于每个下标i暴力找到最大的不被i整除的数。感觉复杂度有点迷说实话。但是要是a[i] = i的话,感觉就是nlogn啊。官方题解说是O(nlogn)。也许?平摊一下感受一下?。

#include <bits/stdc++.h>using namespace std;const int maxn = 100000 + 5;pair<int, int>a[maxn];#define val first#define id secondint main(){    int T;    scanf("%d", &T);    while(T--)    {        int n;        scanf("%d", &n);        for(int i = 1; i <= n; i++)        {            scanf("%d", &a[i].val), a[i].id = i;        }        sort(a + 1, a + n + 1);        for(int i = 2; i <= n; i++)        {            for(int j = n ; j >= 1; j--)            {                if(a[j].id % i != 0)                {                    printf("%d%c", a[j].val, i == n ? '\n' : ' ');                    break;                }            }        }    }    return 0;}

HDU - 6103 - Kirinriki (尺取)

题意:给定m和一个字符串,定义两个字符串disA,B=n1i=0|AiBn1i|。先要求出最长的给定字符串的两个子串满足它们之间的dis小于等于m的长度。

思路:妙啊。这个尺取厉害了。类回文串的感觉,枚举对称轴就行了。尺取能抽掉一个n。

#include <bits/stdc++.h>using namespace std;char s[5000 + 5];int main(){    int T;    scanf("%d", &T);    while(T--)    {        int m;        scanf("%d", &m);        scanf("%s", s);        int n = strlen(s);        int ans = 0;        for(int i = 0; i < n; i++)        {            int sum = 0, l1, r1, l2, r2;            for(l1 = r1 = i, l2 = r2 = i + 1; 0 <= l1 && r2 < n; l1--, r2++)            {                sum += abs(s[l1] - s[r2]);                while(sum > m && l2 <= r2)  sum -= abs(s[r1--] - s[l2++]);                ans = max(ans, r2 - l2 + 1);            }        }        for(int i = 0; i < n; i++)        {            int sum = 0, l1, r1, l2, r2;            for(l1 = r1 = i, l2 = r2 = i + 2; 0 <= l1 && r2 < n; l1--, r2++)            {                sum += abs(s[l1] - s[r2]);                while(sum > m && l2 <= r2)  sum -= abs(s[r1--] - s[l2++]);                ans = max(ans, r2 - l2 + 1);            }        }        printf("%d\n", ans);    }    return 0;}

HDU - 6105- Gameia(博弈)

题意:给出一棵树,Alice 和 Bob 轮流操作, Alice先手, Alice的操作是选一个未染色的点将其染成白色,Bob的操作是选一个未染色的点将其染成黑色,并且和这个点有直连边的点也被强制染成黑色(无论这些直连点之前是否有颜色),Bob还有一个小技能是去掉一条边,最后当所有点都有颜色的时候,如果有白色点则Alice赢,否则Bob赢。

思路:我们多画几个例子很容易发现Bob只有在长度为2的链上才能获胜。所以就是看Bob能否把这棵树切割成一条条长度为2的链。用拓扑排序实现即可。

#include <bits/stdc++.h>using namespace std;const int maxn = 500 +5;vector<int>G[maxn];int vis[maxn], d[maxn];int main(){    int T;    scanf("%d", &T);    while(T--)    {        int n, k;        scanf("%d%d", &n, &k);        for(int i = 1; i <= n; i++) G[i].clear(), d[i] = 0, vis[i] = 0;        for(int i = 2; i <= n; i++)        {            int x;            scanf("%d", &x);            G[i].push_back(x);            G[x].push_back(i);            d[i]++, d[x]++;        }        int cutTimes = 0;        queue<int>que;        for(int i = 1; i <= n; i++)        {            if(d[i] == 1)   que.push(i);        }        while(que.size())        {            int cur = que.front();que.pop();            for(auto o : G[cur])            {                if(vis[o] == 0)                {                    vis[cur] = vis[o] = 1;                    for(auto to : G[o])                    {                        d[to]--;                        if(d[to] == 1)  que.push(to);                    }                    cutTimes++;                    break;                }            }        }        if(cutTimes)    cutTimes--;        int canotCut = 0;        for(int i = 1; i <= n; i++)            if(vis[i] == 0) canotCut = 1;        if(cutTimes > k || canotCut)   puts("Alice");        else puts("Bob");    }    return 0;}

HDU - 6106 - Classes(水容斥)

题意: 学校设立了三门选修课程,假设这些课程是A,B,C。N个班的学生参加了这些课程。现在,学校想计算每班入读至少一门课程的学生人数,并记录最多学生人数。每班上传7份资料,在每班中,选课程A的学生人数,选课程B的学生人数,选课程C的学生人数,选课程AB的学生人数,选课程BC的学生人数,选课程AC的学生人数,选课程ABC的学生人数。根据这7个数据,学校可以计算这个班级的学生人数。现在给你n个班的数据,有些班的数据是错误的,我们应判断出来并忽视它,在剩下数据对的班级里,利用给出的7组数据,求出班级人数,输出班级最多的人数

思路:题意很长,但却是个水题。随便搞搞就行了。

#include <bits/stdc++.h>using namespace std;int main(){    int T;    scanf("%d", &T);    while(T--)    {        int n;        scanf("%d", &n);        int ans = 0;        for(int i = 0; i < n; i++)        {            int a, b, c, ab, bc, ac, abc;            scanf("%d%d%d%d%d%d%d", &a, &b, &c, &ab, &bc, &ac, &abc);            if(a >= ab && a >= ac && b >= ab && b >= bc && c >= ac && c >= bc               && ab >= abc && bc >= abc && ac >= abc               && a >= ab + ac - abc && b >= ab + bc - abc && c >= ac + bc - abc)                ans = max(ans, a + b + c - ab - bc - ac + abc);        }        printf("%d\n", ans);    }    return 0;}
原创粉丝点击