Codeforces Round #677 (Div. 3)
A.Boring Apartments
链接: A.Boring Apartments.
题意:一个调皮的小孩挨个给特殊编号的公寓楼打电话,直到打通为止,1~9999。
input
4
22
9999
1
777
output
13
90
1
66
代码
#include<iostream>
#include<cstring>
using namespace std;
int a[10050];
int main()
{
int t;
int y;
for(int i=1; i<=9; i++)
{
int x = 0;
for(int j=1; j<=4; j++)
{
x = x * 10 + i;
a[x] = j;
}
}
scanf("%d", &t);
while(t--)
{
scanf("%d", &y);
int ans = 0;
int flag = 0;
for(int i=1; i<=9; i++)
{
int x = 0;
for(int j=1; j<=4; j++)
{
x = x * 10 + i;
if(y != x)
{
ans += a[x];
}
else
{
ans += a[y];
flag = 1;
break;
}
}
if(flag)
{
break;
}
}
printf("%d\n", ans);
}
return 0;
}
我这个是比较麻烦的做法,优化的话可以(n % 10 - 1) * 4 + n的位数。
B. Yet Another Bookshelf
题意:强迫症患者要把每本书之间的空隙给取消掉,问要挪动多少次,(以集合为单位进行挪动),一次只能移动一个位置
链接: B. Yet Another Bookshelf.
input
5
7
0 0 1 0 1 0 1
3
1 0 0
5
1 1 0 0 1
6
1 0 0 0 0 1
5
1 1 0 1 1
output
2
0
2
4
1
代码
#include<iostream>
#include<string>
#include<algorithm>
using namespace std;
int a[100];
int main()
{
int n;
int t;
scanf("%d", &t);
while(t--)
{
int n, flag = 0, ans = 0, cnt = 0;
scanf("%d", &n);
for(int i=0; i<n; i++)
{
scanf("%d", &a[i]);
if(a[i] == 1 && !flag)
{
flag = 1;
}
else if(flag && a[i] == 0)
{
cnt++;
}
else if(flag && a[i] == 1)
{
ans += cnt;
cnt = 0;
}
}
printf("%d\n", ans);
}
return 0;
}
思路:其实就是计算0的个数(遇到第一个1之后的),可以看成是书从右往左进行挪动,每次挪到一起就变成了一个集合。
C.Dominant Piranha(大鱼吃小鱼)
链接: C Dominant Piranha.
题意:有一群食人鱼,在一个狭窄的水族箱里面,如果两只不同大小的食人鱼相邻,大鱼会吃小鱼,同时大鱼长大1个单位,问索引(位置)为多少的鱼可以成为最后的王者
input
6
5
5 3 4 4 5
3
1 1 1
5
4 4 3 4 4
5
5 5 4 3 2
3
1 1 2
5
5 4 3 5 5
output
3
-1
4
3
3
1
代码
#include<iostream>
#include<string>
#include<algorithm>
using namespace std;
const int N = 3e5 + 10;
int a[N];
int main()
{
int t;
scanf("%d", &t);
while(t--)
{
int n;
int flag = 0;
scanf("%d" ,&n);
int maxn = 0;
for(int i=1; i<=n; i++)
{
scanf("%d", &a[i]);
maxn = max(a[i], maxn);
}
int j = 1;
a[0] = maxn;
a[n+1] = maxn;
for(int i=1; i<=n; i++)
{
if(a[i] == maxn && (a[i-1] < maxn || a[i+1] < maxn))
{
printf("%d\n", i);
flag = 1;
break;
}
}
if(!flag)
{
printf("-1\n");
}
}
return 0;
}
思路
找到最大的一条鱼,如果左右两边比他小,输出他的位置就可以了,注意最大的那条可能在开头,
D. Districts Connection
链接: D. Districts Connection.
题意:您是该市市长,希望修建n-1条双向道路,以连接所有地区(两个地区可以直接连接,也可以通过其他相连的地区连接)。但是市里面有黑帮,为了防止黑帮起义,不能在有相同黑帮的区之间修路,输出修路的方案。
input
4
5
1 2 2 1 3
3
1 1 1
4
1 1000 101 1000
4
1 2 3 4
output
YES
1 3
3 5
5 4
1 2
NO
YES
1 2
2 3
3 4
YES
1 2
1 3
1 4
代码
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int N = 5555;
int a[N];
int vis[N];
int main()
{
int n, t;
scanf("%d", &t);
while(t--)
{
scanf("%d", &n);
int flag = 0;
int j = 1;
for(int i=1; i<=n; i++)
{
scanf("%d", &a[i]);
if(a[1] == a[i] && i != 1)
{
vis[j++] = i;
}
}
if(j != n)
{
puts("YES");
for(int i=1; i<=n; i++)
{
if(a[1] != a[i])
{
flag = i;
printf("1 %d\n", i);
}
}
for(int k=1; k<j; k++)
{
printf("%d %d\n", flag, vis[k]);
}
}
else
{
puts("NO");
}
}
return 0;
}
思路
找到两个不同黑帮的区,以这两个区为中心修路即可
E. Two Round Dances
链接: E. Two Round Dances.
题意:问两种组合的舞蹈可以有多少不同组合的人参与
input
2
4
8
20
output
1
3
1260
12164510040883200
代码
#include<iostream>
using namespace std;
typedef unsigned long long ull;
ull A(int x, int y)
{
ull ans = 1;
for(int i=0; i<y; i++)
{
ans *= x--;
}
return ans;
}
ull C(int x, int y)
{
ull ans = 1;
for(int i=0; i<y; i++)
{
ans *= x--;
}
ans /= A(y, y);
return ans;
}
int main()
{
int n;
scanf("%d", &n);
ull ans = C(n, n/2) * A(n/2, n/2) * A(n/2, n/2) / (n/2) / (n/2) / 2;
cout << ans;
return 0;
}
思路:
其实就是排列组合问题,先挑选n/2个人,对n/2个人进行排列,因为是圆排列,所以还要除以n/2,最后除以2去重