Codeforces Round #708 (Div. 2)
A. Meximization
其实说白了,这道题就是把数组按从小到大输出,重复的放在最后
本人用的set,略显复杂
#include <bits/stdc++.h>
using namespace std;
int main()
{
int t;
cin>>t;
while(t--)
{
int n;
set<int> s1;
multiset<int> s2;//重复的可能不止一个,所以用multiset
set<int>::iterator it1,it2;
cin>>n;
for(int i=1;i<=n;i++)
{
int x;
cin>>x;
if(!s1.count(x)) s1.insert(x);
else s2.insert(x);
}
for(it1=s1.begin();it1!=s1.end();it1++) cout<<*it1<<' ';
if(!s2.empty())
{
for(it2=s2.begin();it2!=s2.end();it2++)
cout<<*it2<<' ';
}
cout<<endl;
}
return 0;
}
B. M-arrays
一道构造题。
有一个大小为
n
n
n的
a
[
n
]
a[n]
a[n]数组,多个数相加能被
m
m
m整除的话构成一个数组,单独一个也可以单独成为一个数组。问:
a
[
n
]
a[n]
a[n]数组最少可以被分成多少个像这样能被m整除的数组?
(
1
≤
a
i
≤
1
0
9
)
(1≤ai≤10^9)
(1≤ai≤109)
其实我们可以从余数出发。
%m的情况:
1
,
2
,
3......
m
−
2
,
m
−
1
1,2,3......m-2,m-1
1,2,3......m−2,m−1
那我们就可以1和m-1组成一组,2和m-2组成一组,以此类推。余数为0的归到一组,因为题目要求的是最少组数,这些余数为0不用去带其他人。然后我们就可以发现一些规律。
for(int i=1;i<=n;i++)
{
int x;
cin>>x;
mod[x%m]++;
}
读进来数据时,先把它存在
m
o
d
mod
mod数组中
设
a
=
m
o
d
[
i
]
a=mod[i]
a=mod[i],
设
b
=
m
o
d
[
m
−
i
]
b=mod[m-i]
b=mod[m−i]
这样a和b可以凑成一对。
1.如果a和b都不为0,且a和b不是同一个数,那么就是一种。举个例子:比如m为8,i为4,那么m-i也是4,他们只能凑成一种。
2.不然就是
a
b
s
(
m
o
d
[
i
]
−
m
o
d
[
i
−
1
]
)
abs(mod[i]-mod[i-1])
abs(mod[i]−mod[i−1])(这个我也不知道该怎么解释,反正多走几遍数据就是了)
#include <bits/stdc++.h>
using namespace std;
int main()
{
int t;
cin>>t;
while(t--)
{
int n,m,ans=0;
cin>>n>>m;
int mod[100000]={0};
for(int i=1;i<=n;i++)
{
int x;
cin>>x;
mod[x%m]++;
}
if(mod[0]>0) ans++;
for(int i=1;i<=m/2;i++)
{
if(mod[i]&&mod[i]==mod[m-i]) ans++;
else ans=ans+abs(mod[i]-mod[m-i]);
}
cout<<ans<<endl;
}
return 0;
}
C1. k-LCM (easy version)
分类讨论的一道题目。
1.n奇数
那么三个数分别是:
n
/
2
,
n/2,
n/2,
n
/
2
n/2
n/2 和
1
1
1
2.n为偶数
可以转化为
(
n
−
1
)
+
1
(n-1)+1
(n−1)+1
n-1是奇数按上面方法分解
最后整合一下就是
n
/
2
−
1
,
n
/
2
−
1
,
2
n/2-1,n/2-1,2
n/2−1,n/2−1,2
3.但是还有一些数是例外。
例如8如果按照方法2来分解,就会得到
3
,
3
,
2
3,3,2
3,3,2
12如果按照方法2来分解,就会得到
5
,
5
,
2
5,5,2
5,5,2
这都是不符合要求的。
试了几个,我们发现这些数有这样一个特点:
2
n
+
2
(
n
为
奇
数
)
2n+2(n为奇数)
2n+2(n为奇数)
那我们可以进一步写成:
2
(
2
k
+
1
)
+
2
2(2k+1)+2
2(2k+1)+2
化简可得:
4
k
+
4
4k+4
4k+4
可见这些数都是4的倍数
其实直接一眼看出来
那我们该怎么办呢?这个时候,样例又给了我们启发:
input: 8 3
output:4 2 2
n / 2 , n / 4 , n / 4 n/2,n/4,n/4 n/2,n/4,n/4多试了几个,就他了!!!
#include <bits/stdc++.h>
using namespace std;
int main()
{
int t;
cin>>t;
while(t--)
{
int n,k;
cin>>n>>k;
if(n%2!=0)
{
cout<<n/2<<' '<<n/2<<' '<<1;
cout<<endl;
}
else if(n%4!=0)
{
cout<<n/2-1<<' '<<n/2-1<<' '<<2;
cout<<endl;
}
else
{
cout<<n/2<<' '<<n/4<<' '<<n/4;
cout<<endl;
}
}
return 0;
}
C2. k-LCM (hard version)
数学老师曾经告诉我们:一个题目有多个问,那么只些问之间必然有联系!
C2告诉我不仅有联系,而且可以直接copy
C1我们已经处理了
k
=
3
k=3
k=3的情况,那么C2直接套就可以了。
k
>
3
k>3
k>3的部分直接输出1,剩下来的
n
−
(
k
−
3
)
=
n
−
k
+
3
n-(k-3)=n-k+3
n−(k−3)=n−k+3部分同C1
#include <bits/stdc++.h>
using namespace std;
int main()
{
int t;
cin>>t;
while(t--)
{
int n,k;
cin>>n>>k;
k-=3;
for(int i=1;i<=k;i++)
cout<<"1"<<' ';
n-=k;
if(n%2!=0)
{
cout<<n/2<<' '<<n/2<<' '<<1;
cout<<endl;
}
else if(n%4!=0)
{
cout<<n/2-1<<' '<<n/2-1<<' '<<2;
cout<<endl;
}
else
{
cout<<n/2<<' '<<n/4<<' '<<n/4;
cout<<endl;
}
}
return 0;
}