两场CF div2 的题目,最后还是只过7道
A.Circle Line 此题较水,判断min(正向,反向)即可。
B.New Problem 在给定一些字符串(全由小写字母组成)前提下,找出最小的串,要求它不属于任何给定串的子串。串越短、字符越小优先。
回溯写起来应该很方便
看数据量是30,而如果给定字符串长度都为2,则有26*26种可能,所以子串长度只有1或2的可能。所以枚举子串长度为1,2的可能.......
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <map>
# define MAX 105
# define INF 0x7FFFFFFF
using namespace std;
string m,n,p,q;
int main ()
{
int a,b,c,d,f1,f2;
int i,j;
cin >> a;
for(i=1; i<=a; i++)
{
cin >> m;
n = n + '!';
n = n + m;
}
for(i='a'; i<='z'; i++)
{
p = i;
b = n.find(p);
if(b == -1)
{
cout << p << endl;
return 0;
}
}
for(i='a'; i<='z'; i++)
{
for(j='a'; j<='z'; j++)
{
p = i;
q = j;
p = p + q;
b = n.find(p);
if(b == -1)
{
cout << p << endl;
return 0;
}
}
}
return 0;
}
C题并查集,按照语言相通分为n类,最后只要派出n-1个人学一种语言,就能连成一片了。特殊情况,每个人都不会一种语言,此时特殊处理就行。
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
# define INF 0x7FFFFFFF
using namespace std;
#define MAX 105
int par[MAX],lan[MAX][MAX],vis[MAX],cnt[MAX];
int n,m,k;
int find(int x)
{
while(par[x] != x)
x = par[x];
return x;
}
void connect(int a,int b)
{
if(a < b)
par[b] = a;
else
par[a] = b;
}
int main()
{
int a,i,j;
while(cin >> n >> m)
{
int num = 0;
memset(lan,0,sizeof(lan));
memset(vis,0,sizeof(vis));
memset(cnt,0,sizeof(cnt));
for(i=1; i<=n; i++)
par[i] = i;
for(i=1; i<=n; i++)
{
cin >> k;
if(k == 0)
par[i] = -1;
for(j=0; j<k; j++)
{
cin >> a;
lan[a][i] = 1;
}
}
for(i=1; i<=m; i++)
{
memset(vis,0,sizeof(vis));
for(j=1; j<=n; j++)
{
if(lan[i][j] == 1 && vis[j] == 0)
{
vis[j] = 1;
for(int k=1; k<=n; k++)
{
if(vis[k] == 0 && lan[i][k] == 1)
{
int aa = find(j);
int bb = find(k);
if(aa != bb)
connect(aa,bb);
}
}
}
}
}
for(i=1; i<=n; i++)
{
if(par[i] == -1)
num ++;
else
cnt[find(i)] = 1;
}
int ans = 0;
for(i=1; i<=n; i++)
{
if(cnt[i] == 1)
ans ++;
}
if(ans != 0)
cout << ans - 1 + num << endl;
else
cout << num << endl;
}
return 0;
}
D.Set of Point
此题神题啊,自己是完全没理解啥意思,大神讲解后才勉强明白。
在平面坐标中给出n个点,在这n个点的任意子集中,要求找出最多为m条边的凸多边形。输入自己认为正确的n个点的坐标,不行则-1。
在坐标点数超过4,m为3(找三角形)时,找不到符合题意的点,其它则都能
为了找凸多边形,利用凸函数,所以在y = x * x上先找m个点,保证边数为m的凸多边形。而其它点与这个凸多边形相连要产生凹多边形,
找 y = - x * x - MAX,MAX为很大的数。
#include <iostream>
#include <cstdio>
using namespace std;
# define MAX 1000000
int main()
{
int m,n,i;
while(cin >> n >> m)
{
if(m == 3 && n >= 5)
{
cout << -1 << endl;
continue;
}
for(i=0; i<m; i++)
{
printf("%d %d\n",i,i*i);
}
for(i=0; i<n-m; i++)
{
printf("%d %d\n",-i,-(i*i)-MAX);
}
}
return 0;
}
F较水的题目,偶数不变,奇数处理即可。
G.Convex Shape
一看很神,但数据量为50,所以直接模拟各种可能得出答案。写的有些繁琐而已。
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
int m, n;
char map[51][51];
bool Judge(int i0, int j0)
{
for(int i1 = 0; i1 < n; i1++)
for(int j1 = 0; j1 < m; j1++)
{
if(map[i1][j1] == 'B' && (i1 != i0 || j1 != j0))
{
if(i1 == i0)
{
int d = j1 > j0 ? 1 : -1;
for(int k = j0 + d; ; k += d)
{
if(map[i0][k] == 'W') return false;
if(k == j1) break;
}
}
else if(j1 == j0)
{
int d = i1 > i0 ? 1 : -1;
for(int k = i0 + d; ; k += d)
{
if(map[k][j0] == 'W') return false;
if(k == i1) break;
}
}
else
{
bool tag = true;
int k, d;
d = i1 > i0 ? 1 : -1;
for(k = i0 + d; ; k += d)
{
if(map[k][j0] == 'W')
{
tag = false;
break;
}
if(k == i1) break;
}
if(tag)
{
d = j1 > j0 ? 1 : -1;
for(k = j0 + d; ; k += d)
{
if(map[i1][k] == 'W')
{
tag = false;
break;
}
if(k == j1) break;
}
}
if(!tag)
{
tag = true;
d = j1 > j0 ? 1 : -1;
for(k = j0 + d; ; k += d)
{
if(map[i0][k] == 'W')
{
tag = false;
break;
}
if(k == j1) break;
}
if(tag)
{
d = i1 > i0 ? 1 : -1;
for(k = i0 + d; ; k += d)
{
if(map[k][j1] == 'W')
{
tag = false;
break;
}
if(k == i1) break;
}
}
}
if(!tag) return false;
}
}
}
return true;
}
int main()
{
bool ok;
while(scanf("%d %d", &n, &m) != EOF)
{
ok = true;
for(int i = 0; i < n; i++)
scanf("%s", map[i]);
for(int i = 0; i < n && ok; i++)
{
for(int j = 0; j < m && ok; j++)
{
if(map[i][j] == 'B')
ok = Judge(i, j);
}
}
if(ok) printfs("YES\n");
else printfs("NO\n");
}
return 0;
}
H.k-Multiple Free Set
以前看到过类似的题目,但一时想不起来怎么做,悲剧了。
把较小的先放入集合中是最优的,利用sort排序好,放入集合的数标记一下,该数的k倍大小也标记,被标记的则无法进入集合。最后进入集合个数也是最优解之一。
#include <iostream>
#include <algorithm>
#include <map>
# define MAX 1000050
using namespace std;
map <int,int> my;
int n,k,a[MAX],ans;
int main()
{
int i,j;
cin>> n >> k;
for(i=0; i<n; i++)
cin >> a[i];
ans=0;
sort(a,a+n);
for(i=0; i<n; i++)
{
if(a[i] % k || my[a[i]/k] == 0)
{
ans++;
my[a[i]] = ans;
}
}
cout<< ans <<endl;
return 0;
}