A.题意:第一个字母相同的的人放在一个教室会聊天,给出一些人的名字,问如何将他们分配到两个教室,使得聊天的pair对最少…
挺水的一个题,只要将同名的人平均分到两个教室就可以了。
#include <iostream>
#include <cmath>
using namespace std;
int arr[30];
int Cal(int n){
if(!n) return 0;
return n*(n-1)/2;
}
int main()
{
int n; cin >> n;
string str;
for(int i = 0; i < n; ++i){
cin >> str;
++arr[str[0]-'a'];
}
int tot = 0;
for(int i = 0; i < 26; ++i){
int maxx = ceil(arr[i]*1.0/2);
tot += Cal(maxx) + Cal(arr[i]-maxx);;
}
cout << tot << endl;
return 0;
}
B.使得每一行每一列都会出现所有的元音字母
很容易想到当 n <5的时候肯定不满足,所以考虑n>=5的时候,然后构造一下就好了
#include <iostream>
using namespace std;
char cc[105][105];
char yuan[5] = {'a','e','i','o','u'};
int main()
{
int k; cin >> k;
int row = 0,col = 0 ;
for(int i = 5; i < k; ++i){
if(!(k%i)){
row = i,col = k/i;
break;
}
}
if(row < 5 || col < 5){
cout << -1 << endl;
return 0;
}
int tot = 0;
for(int i = 0; i < row; ++i){
for(int j = 0; j < col; ++j){
cc[i][j] = yuan[(i+j)%5];
}
}
for(int i = 0; i < row; ++i){
for(int j = 0; j < col; ++j){
if(cc[i][j]=='\0'){
}
else cout << cc[i][j];;
}
}
cout << endl;
return 0;
}
C.题意指的是 给你一些数字,让你找出 pair(x,y) 使得
m
i
n
(
∣
x
−
y
∣
,
∣
x
+
y
∣
)
<
=
∣
x
∣
<
=
∣
y
∣
<
=
m
a
x
(
∣
x
+
y
∣
,
∣
x
−
y
∣
)
min(|x-y|,|x+y|)<=|x|<=|y|<=max(|x+y|,|x-y|)
min(∣x−y∣,∣x+y∣)<=∣x∣<=∣y∣<=max(∣x+y∣,∣x−y∣)
那么对于每个数来说可以将上述式子平方转换一下得到
x
x
x和
y
y
y的关系式
当时做的时候考虑了正负(最后好像是没有影响的只要取绝对值后直接分析即可)
最后记得加longlong,会溢出的…
#include <iostream>
#include <algorithm>
#include <map>
using namespace std;
struct Node{
long long l,r;
};
const long long MAX = 2e5+5;
long long arr[MAX];
int main()
{
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
map<long long,Node> mp;
long long n; cin >> n;
for(long long i = 0; i < n; ++i) cin >> arr[i];
sort(arr,arr+n);
for(long long i = 0; i < n; ++i){
mp[arr[i]].l = min(i,mp[arr[i]].l);
mp[arr[i]].r = max(i,mp[arr[i]].r);
}
long long tot = 0;
for(long long i = 0; i < n; ++i){
if(arr[i]>0){ // 如果是正数 先找一个最大值2*x的位置
long long rr = upper_bound(arr,arr+n,arr[i]*2)-arr-1;
tot += abs(rr - i);
// 再考虑异号的(一定要满足 y <= -2x) 假设 y = arr[i] 即 -y <= x <= y/-2; 这里把正数当作y
// 第二种 x = arr[i] y>=-2x && y <= -x 即 -2y <= x <= y/-2;
long long xx = upper_bound(arr,arr+n,arr[i]*1.0/-2)-arr;
long long yyy = lower_bound(arr,arr+n,-2*arr[i])-arr;
tot += (xx-yyy);
}
if(arr[i]<=0){
// 把arr[i] 看成是 x 的话 要找到 一个y>=2x的位置
// 只考虑同号的情况
long long rr = lower_bound(arr,arr+n,arr[i]*2)-arr;
tot += i-rr;
}
}
cout << tot <<endl;
return 0;
}
D题
E题也是个思维题来着…也涉及到一些数论知识吧
这题的意思是: 每天买
k
i
k_i
ki个物品,但是不记得每个商店里的物品权值
a
i
a_i
ai,问你有没有可能存在一组
a
i
a_i
ai使得每一天选择的
k
i
k_i
ki个物品的
L
C
M
LCM
LCM都大于其补集的
L
C
M
LCM
LCM,其中LCM的定义是 一个最小整数使得他能被这个整数集合的所有元素整除
结论: 如果两两集合都存在交集,那么就 p o s s i b l e possible possible,反之 i m p o s s i b l e impossible impossible
首先假设两两集合不存在交集
总集合是
(
a
,
b
,
c
,
d
,
e
)
(a,b,c,d,e)
(a,b,c,d,e) 那么第一天选择的集合是
(
a
,
b
)
(a,b)
(a,b),那么其补集就是
(
c
,
d
,
e
)
(c,d,e)
(c,d,e)
要满足
L
C
M
(
a
,
b
)
>
L
C
M
(
c
,
d
,
e
)
LCM(a,b) > LCM(c,d,e)
LCM(a,b)>LCM(c,d,e)
那么再考虑第二天选择的是
(
c
,
d
)
(c,d)
(c,d),其补集就是
(
a
,
b
,
e
)
(a,b,e)
(a,b,e) 要满足
L
C
M
(
c
,
d
)
>
L
C
M
(
a
,
b
,
e
)
LCM(c,d)>LCM(a,b,e)
LCM(c,d)>LCM(a,b,e)
但是很显然
L
C
M
(
a
,
b
,
e
)
>
=
L
C
M
(
a
,
b
)
LCM(a,b,e) >= LCM(a,b)
LCM(a,b,e)>=LCM(a,b)
L
C
M
(
c
,
d
,
e
)
>
=
L
C
M
(
c
,
d
)
LCM(c,d,e) >= LCM(c,d)
LCM(c,d,e)>=LCM(c,d) 于是就产生了矛盾
所以最终只需要判断每两天之间是不是存在交集就可以了
#include <iostream>
#include <vector>
#include <set>
using namespace std;
const int MAX = 1e4+5;
set<int>st[MAX];
int main()
{
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
int m,n; cin >> m >> n;
for(int i = 0,k; i < m; ++i){
cin >> k;
for(int j = 0,x; j < k; ++j){
cin >> x;
st[i].insert(x);
}
}
for(int i = 0; i < m; ++i){
for(int j = i+1; j < m; ++j){
bool ishave = false;
for(auto y : st[i]){
if(st[j].count(y)){
ishave = true;
break;
}
}
if(!ishave){
cout << "impossible" << endl;
return 0;
}
}
}
cout << "possible" << endl;
return 0;
}
F