2015ACM/ICPC亚洲区沈阳站

5510  Bazinga

题意:给出n个字符串,求满足条件的最大下标值或层数

条件:该字符串之前存在不是 它的子串 的字符串

求解si是不是sj的子串,可以用kmp算法之类的。

strstr是黑科技,比手写的kmp快。if(strstr(s[i], s[j]) == NULL),则Si不是Sj的子串。

还有一个重要的剪枝:对于一个串,如果当前找到的串是它的母串,则下一次这个串不用遍历。

 1 #include <set>
 2 #include <queue>
 3 #include <cstdio>
 4 #include <vector>
 5 #include <cstring>
 6 #include <algorithm>
 7 using namespace std;
 8 typedef long long LL;
 9 #define mem(x,y) memset(x, y, sizeof(x))
10 #define lson l,m,rt << 1
11 #define rson m+1,r,rt << 1 | 1
12 int gcd(int a,int b){return b == 0 ? a : gcd(b, a % b);}
13 int lcm(int a,int b){return a / gcd(a, b) * b;}
14
15 int T, n;
16 char s[505][2005];
17 int vis[505];
18
19 int main()
20 {
21     scanf("%d", &T);
22     for(int Case = 1; Case <= T; Case++)
23     {
24         mem(vis, 0);
25         scanf("%d", &n);
26         getchar();
27         for(int i = 1; i <= n; i++)
28         {
29             scanf("%s", s[i]);
30         }
31         int ans = -1;
32         for(int i = 2; i <= n; i++)
33         {
34             int ok = 0;
35             for(int j = i - 1; j >= 1; j--)
36             {
37                 if(vis[j]) continue;
38                 if(strstr(s[i], s[j]) == NULL)//sj 不是 si的子串
39                 {
40                     ok = 1;
41                     break;
42                 }
43                 else
44                 {
45                     vis[j] = 1;//重要剪枝
46                 }
47             }
48             if(ok) ans = i;
49         }
50         printf("Case #%d: %d\n", Case, ans);
51     }
52     return 0;
53 }

5512  Pagodas

题意:有n个庙经过长时间风吹雨打需要修补,只有两座(被标记为a,b)完好无损不需要修补,有两个和尚轮流去修补这n-2个庙,每个和尚每次只能修补一个庙标记为i,并要求i满足i=j+k或者i=j-k,每个庙只能被修建一次;其中j和k代表已经修建好的庙,Yuwgna先开始,问最后谁不能修建谁输;

更相减损术!(gcd里头:辗转相除法,更相减损术,自行百度)

更相减损术:

第一步:任意给定两个正整数;判断它们是否都是偶数。若是,则用2约简;若不是则执行第二步。

第二步:以较大的数减较小的数,接着把所得的差与较小的数比较,并以大数减小数。继续这个操作,直到所得的减数和差相等为止。

则第一步中约掉的若干个2与第二步中等数的乘积就是所求的最大公约数。

所以它在1-n里头,只要是它的最小公因数的倍数的数都是可以选择的点,所以答案是n / gcd(x, y)

主要是由i = j - k联想出来的。

 1 #include <set>
 2 #include <queue>
 3 #include <cstdio>
 4 #include <vector>
 5 #include <cstring>
 6 #include <algorithm>
 7 using namespace std;
 8 typedef long long LL;
 9 #define mem(x,y) memset(x, y, sizeof(x))
10 #define lson l,m,rt << 1
11 #define rson m+1,r,rt << 1 | 1
12 int gcd(int a,int b){return b == 0 ? a : gcd(b, a % b);}
13 int T, n, x, y;
14
15 int main()
16 {
17     scanf("%d", &T);
18     for(int Case = 1; Case <= T; Case++)
19     {
20         scanf("%d%d%d", &n, &x, &y);
21         int g = gcd(x, y);
22         int cnt = n / g;
23         printf("Case #%d: ", Case);
24         printf("%s\n", cnt & 1 ? "Yuwgna" : "Iaka");
25     }
26     return 0;
27 }

5521  Meeting

题意:给你一个n个点,m个集合的图,每个集合中的点都可以以di的距离相互的到达,问你两个人同时从1和n出发,会在那个点相遇。

每个集合内部里的所有的边都是互通的,如果一个个连就要n²了,可以采用增加虚拟结点的方式,来减少点。虚拟一个s,一个e,把他们连接起来。

 1 for(int i = 1; i <= m; i++)
 2 {
 3     int w, num;
 4     int s = n + i, e = n + i + m;
 5     scanf("%d%d", &w, &num);
 6  G[s].push_back(edge(e, w));
 7     while(num--)
 8     {
 9         int x;
10         scanf("%d", &x);
11         G[e].push_back(edge(x, 0));
12         G[x].push_back(edge(s, 0));
13     }
14 }
  1 //题意:给你一个n个点,m个集合的图,每个集合中的点都可以以di的距离相互的到达,问你两个人同时从1和n出发,会在那个点相遇。
  2 #include <set>
  3 #include <queue>
  4 #include <cstdio>
  5 #include <vector>
  6 #include <cstring>
  7 #include <algorithm>
  8 using namespace std;
  9 typedef long long LL;
 10 #define mem(x,y) memset(x, y, sizeof(x))
 11 #define lson l,m,rt << 1
 12 #define rson m+1,r,rt << 1 | 1
 13 int gcd(int a,int b){return b == 0 ? a : gcd(b, a % b);}
 14 int lcm(int a,int b){return a / gcd(a, b) * b;}
 15
 16 int T, n, m, Case;
 17 LL ans;
 18 const int maxn_v = 1e5 + 5;
 19 const LL INF = 1e18;
 20
 21 const int ssize = 2e6 + 1e5 + 5;
 22 LL d1[ssize], d2[ssize];
 23
 24 struct edge
 25 {
 26     int to;
 27     LL co;
 28     edge(int tt, LL cc):to(tt), co(cc){}
 29     bool operator < (const edge &other)const
 30     {
 31         return co > other.co;
 32     }
 33 };
 34 vector<edge>G[ssize];
 35 void init()
 36 {
 37     for(int i = 1; i <= n + 2 * m; i++) G[i].clear();
 38     ans = INF;
 39 }
 40 void dijkstra(int s, LL dis[])
 41 {
 42     for(int i = 1; i <= n + 2 * m; i++) dis[i] = INF;
 43     priority_queue<edge>que;
 44     dis[s] = 0;
 45     que.push(edge(s, dis[s]));
 46     while(!que.empty())
 47     {
 48         edge p = que.top();que.pop();
 49         int v = p.to;
 50         if(dis[v] < p.co) continue;
 51         for(int i = 0; i < G[v].size(); i++)
 52         {
 53             edge e = G[v][i];
 54             if(dis[e.to] > dis[v] + e.co)
 55             {
 56                 dis[e.to] = dis[v] + e.co;
 57                 que.push(edge(e.to, dis[e.to]));
 58             }
 59         }
 60     }
 61 }
 62
 63 void solve()
 64 {
 65     dijkstra(1, d1);
 66     dijkstra(n, d2);
 67     ans = INF;
 68     for(int i = 1; i <= n; i++)
 69     {
 70         ans = min(ans, max(d1[i], d2[i]));
 71     }
 72     printf("Case #%d: ", Case);
 73
 74     if(ans == INF)
 75         printf("Evil John\n");
 76     else
 77     {
 78         printf("%I64d\n", ans);
 79         int cnt = 0;
 80         for(int i = 1; i <= n; i++)
 81         {
 82             if(ans == max(d1[i], d2[i])) cnt++;
 83         }
 84         for(int i = 1; i <= n; i++)
 85         {
 86             if(ans == max(d1[i], d2[i])) cnt--, printf("%d%c", i, cnt ? ‘ ‘ : ‘\n‘ );
 87         }
 88     }
 89 }
 90
 91
 92 int main()
 93 {
 94     scanf("%d", &T);
 95     for(Case = 1; Case <= T; Case++)
 96     {
 97         scanf("%d%d", &n, &m);
 98         init();
 99         for(int i = 1; i <= m; i++)
100         {
101             int w, num;
102             int s = n + i, e = n + i + m;
103             scanf("%d%d", &w, &num);
104             G[s].push_back(edge(e, w));
105             while(num--)
106             {
107                 int x;
108                 scanf("%d", &x);
109                 G[e].push_back(edge(x, 0));
110                 G[x].push_back(edge(s, 0));
111             }
112         }
113         solve();
114     }
115     return 0;
116 }
时间: 2024-10-07 17:48:33

2015ACM/ICPC亚洲区沈阳站的相关文章

hdu5512 Pagodas(2015ACM/ICPC亚洲区沈阳站-重现赛(感谢东北大学) )

Pagodas Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 14 Accepted Submission(s): 13 Problem Description n pagodas were standing erect in Hong Jue Si between the Niushou Mountain and the Yuntai M

2015ACM/ICPC亚洲区沈阳站-重现赛 1004 Pagodas

Problem Description: n pagodas were standing erect in Hong Jue Si between the Niushou Mountain and the Yuntai Mountain, labelled from 1 to n. However, only two of them (labelled aand b, where 1≤a≠b≤n) withstood the test of time. Two monks, Yuwgna and

hdu 5510 Bazinga (kmp+dfs剪枝) 2015ACM/ICPC亚洲区沈阳站-重现赛(感谢东北大学)

废话: 这道题很是花了我一番功夫.首先,我不会kmp算法,还专门学了一下这个算法.其次,即使会用kmp,但是如果暴力枚举的话,还是毫无疑问会爆掉.因此在dfs的基础上加上两次剪枝解决了这道题. 题意: 我没有读题,只是队友给我解释了题意,然后我根据题意写的题. 大概意思是给n个字符串,从上到下依次标记为1——n,寻找一个标记最大的串,要求这个串满足:标记比它小的串中至少有一个不是它的子串. 输入: 第一行输入一个整型t,表示共有t组数据. 每组数据首行一个整型n,表示有n个串. 接下来n行,每行

【hdu 5521】【 2015ACM/ICPC亚洲区沈阳站重现赛】Meeting 题意&题解&代码

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5521 题意: 输入:输入n表示有n个点,输入m表示有m个点集. 接下来m行信息,每行先输入一个t表示这个点集中任意两点费时为t,再输入一个s,表示有s个点在这个点集中,接下来s个数表示这些数在这个点集之中. 现在有两个人,其中一个人住在点1,另一个人住在点n,如果两个人要见面,同时出发,可以走走停停,问需要最少时间是多少,有哪几个点能被当成见面点. 题解: 我们发现这道题如果建好图之后就直接是一个

【hdu 5517】【2015ACM/ICPC亚洲区沈阳站】Triple 题意&题解&代码(C++)

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5517 题意: 给出n个二元组<a,b>和m个三元组<c,d,e>现在将其组合成一个新的三元组集合,新三元组中允许有重复元素,一个二元组和一个三元组可以组合当且仅当b==e时将其组合成<a,c,d>,在新组合的三元组中任取一元素<a,b,c>,如果在新组合存在一个元素<u,v,w>使得u!=a && v!=b && w

【hdu 5512】【 2015ACM/ICPC亚洲区沈阳站】Pagodas 题意&题解&代码(C++)

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5512 题意: 给出n个点和a,b两个初始被标记的点,每次可以选取已经被标记点中的两个点 i , j 来标记新点 i+j 或 i-j,两个人轮流标记,如果谁无法标记,谁输,输出赢的人. 题解: 首先我们发现当a,b互质时,它通过以上操作,一定能标记到1号点,接着所有点都可以标记,当a,b不互质时,多写几个数找规律发现gcd(a,b)倍数的位置都可以标记到. 代码: #include<iostream

【hdu 5510】【2015ACM/ICPC亚洲区沈阳站-重现赛 】Bazinga 题意&题解&代码(C++)

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5510 题意: 给出n个字符串,求下标最大的字符串,存在下标小于它的字符串中有字符串不是他的子串. 题解: 首先能想到kmp+n^2暴力匹配,但是感觉会超时,因此我们需要加一些剪枝,水题,不要被他的数据范围吓到.. 代码: #include<iostream> #include<algorithm> #include<stdio.h> #include<string.

HDU 5521 Meeting(好题,最短路,2015ACM/ICPC亚洲区沈阳站)

1 /** 2 题意:有n个点,m个集合 3 集合内的点 两两 到的时间为 ti; 4 有两个人 在1,n; 输出最小相遇时间,以及哪些点(可以走走停停); 5 6 思路:****将集合抽象为点.访问过的集合不再访问. 7 Set集合抽象的点. 8 Belong属于哪个集合. 9 */ 10 #include<bits/stdc++.h> 11 using namespace std; 12 typedef long long ll; 13 const ll INF = 0x7f7f7f7f;

HDU 5950 Recursive sequence 【递推+矩阵快速幂】 (2016ACM/ICPC亚洲区沈阳站)

Recursive sequence Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 249    Accepted Submission(s): 140 Problem Description Farmer John likes to play mathematics games with his N cows. Recently, t