昨天又又又又那个了..
今天上午写了一道1600分的题,写了快2个小时也没整出来....
然后又做了一道1500分异或的题,又没出来
下午打航电多校,只出了一题..其他的题直接离谱...
这题我想的极其复杂.但是大体上思路是正确的
分了字典序最小的字母大于k等于k和小于k的情况.然后还考虑了其他特殊的情况
麻烦死了..
cpp
#include<cstdio>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<string.h>
#include<queue>
#include<stack>
#include<deque>
#include<vector>
#include<map>
#include<set>
#include <utility>
#include <list>
using namespace std;
typedef long long ll ;
typedef unsigned long long ull ;
#define pii pair<int,int>
const int inf = 0x3f3f3f3f;//106110956
inline int read(){
int x = 0, f = 1;
char ch = getchar();
while(ch < '0' || ch > '9'){
if (ch == '-')
f = -1;
ch = getchar();
}
while(ch >= '0' && ch <= '9'){
x = (x<<1) + (x<<3) + (ch^48);
ch = getchar();
}
return x * f;
}
void print(__int128 num) {
if(num) {
print(num/10);
putchar(num%10+'0');
}
}
int t;
int main(){
scanf("%d",&t);
while(t--){
int n,k;
scanf("%d%d",&n,&k);
string s;
cin>>s;
vector<int>a(30);
int num=0;
for(int i=0;i<s.length();i++){
a[s[i]-96]++;
if(a[s[i]-96]==1)num++;
}
int cnt;
int pos;
for(int i=1;i<=27;i++){
if(a[i]!=0){
cnt=a[i];
pos=i;
break;
}
}
if(k==1){
for(int i=1;i<=27;i++){
for(int j=1;j<=a[i];j++){
cout<<char(i-1+'a');
}
}
printf("\n");
continue;
}
if(num==1){
if(n%k==0){
n=n/k;
}else{
n=n/k+1;
}
int flag=0;
for(int i=1;i<=27;i++){
if(flag)break;
if(a[i]!=0){
for(int j=1;j<=n;j++){
cout<<char(i-1+'a');
flag=1;
}
}
}
printf("\n");
continue;
}
if(n==k){
for(int i=27;i>=1;i--){
if(a[i]!=0){
cout<<char(i-1+'a');
break;
}
}
printf("\n");
continue;
}
if(cnt==k){
cout<<char(pos-1+'a');
if(num-1>=2){
for(int i=pos+1;i<=27;i++){
for(int j=1;j<=a[i];j++){
cout<<char(i-1+'a');
}
}
}else{
for(int i=pos+1;i<=27;i++){
for(int j=1;j<=a[i];j=j+k){
cout<<char(i-1+'a');
}
}
}
printf("\n");
continue;
}
if(cnt>k){
for(int i=1;i<=cnt-k+1;i++){
cout<<char(pos-1+'a');
}
if(num-1>=2){
for(int i=pos+1;i<=27;i++){
for(int j=1;j<=a[i];j++){
cout<<char(i-1+'a');
}
}
printf("\n");
continue;
}else{
for(int i=pos+1;i<=27;i++){
for(int j=1;j<=a[i];j++){
cout<<char(i-1+'a');
}
}
}
}
if(cnt<k){
int flag=0;
for(int i=pos+1;i<=27;i++){
if(flag)break;
for(int j=1;j<=a[i];j++){
cnt++;
if(cnt==k){
cout<<char(i-1+'a');
flag=1;
break;
}
}
}
printf("\n");
}
}
return 0;
}
感觉写的没啥问题.但就是没过,标准答案是真的简单!!(当我写到这里时已经过了快24小时了..)
还有就是我不会string的排序...
现在会了...sort(s.begin(),s.end())
1.如果字典序最小的字母的数量小于k,那么直接输出第k个字母即可
2.如果字典序最小的字母的数量大于等于k,输出一个s[0],如果s[k]==s[n-1]的话就k组均分
否则就全部加到第一组上
当时我考虑了字典序最小的字母的数量大于等于k的情况分了2种:(只有一种字母的情况已经特殊考虑了)
1.等于k:如果s[k]到s[n-1]的字母种类大于1,就全部输出,否则说明种类等于1就均分
2大于k:这个情况我考虑错了.一开始我想着把第一个字母均分为k组
其实最优的是把k-1个字母分成k-1组,然后第一组接后面的全部
cpp
#include<cstdio>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<string.h>
#include<queue>
#include<stack>
#include<deque>
#include<vector>
#include<map>
#include<set>
#include <utility>
#include <list>
using namespace std;
typedef long long ll ;
typedef unsigned long long ull ;
#define pii pair<int,int>
const int inf = 0x3f3f3f3f;//106110956
inline int read(){
int x = 0, f = 1;
char ch = getchar();
while(ch < '0' || ch > '9'){
if (ch == '-')
f = -1;
ch = getchar();
}
while(ch >= '0' && ch <= '9'){
x = (x<<1) + (x<<3) + (ch^48);
ch = getchar();
}
return x * f;
}
void print(__int128 num) {
if(num) {
print(num/10);
putchar(num%10+'0');
}
}
int t;
int main(){
scanf("%d",&t);
while(t--){
int n,k;
scanf("%d%d",&n,&k);
string s;
cin>>s;
sort(s.begin(),s.end());
if(s[0]!=s[k-1]){
cout<<s[k-1]<<endl;
}else{
cout<<s[0];
if(s[k]!=s[n-1]){
for(int i=k;i<=n-1;i++){
cout<<s[i];
}
}else{
for(int i=k;i<=n-1;i=i+k){
cout<<s[i];
}
}
cout<<endl;
}
}
return 0;
}
这题纯贪心....
我吐了我写了快2个小时二分,最后也没整出来..结果是纯贪心?
但是仔细想一想确实是这样的...
首先排序
cpp
#include<cstdio>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<string.h>
#include<queue>
#include<stack>
#include<deque>
#include<vector>
#include<map>
#include<set>
#include <utility>
#include <list>
using namespace std;
typedef long long ll ;
typedef unsigned long long ull ;
#define pii pair<int,int>
const int inf = 0x3f3f3f3f;//106110956
inline int read(){
int x = 0, f = 1;
char ch = getchar();
while(ch < '0' || ch > '9'){
if (ch == '-')
f = -1;
ch = getchar();
}
while(ch >= '0' && ch <= '9'){
x = (x<<1) + (x<<3) + (ch^48);
ch = getchar();
}
return x * f;
}
void print(__int128 num) {
if(num) {
print(num/10);
putchar(num%10+'0');
}
}
const int N=1e5+5;
int n;
int main(){
vector<int>a,b(N);
scanf("%d",&n);
for(int i=1;i<=n;i++){
int x;
scanf("%d",&x);
a.push_back(x);
}
sort(a.begin(),a.end());
int id=0;
for(int i=1;i<n;i=i+2){
b[i]=a[id++];
}
for(int i=0;i<n;i=i+2){
b[i]=a[id++];
}
int ans=0;
for(int i=1;i<n-1;i++){
if(b[i-1]>b[i]&&b[i]<b[i+1]) ans++;
}
printf("%d\n",ans);
for(int i=0;i<n;i++){
cout<<b[i]<<" ";
}
return 0;
}
我们预设一个vector,然后vector的偶数项为最小的前i项,然后剩余的项为奇数项
如果a[i-1]>a[i]&&a[i]<a[i+1],答案就++
这题还是很有意思的..
一道规律题.手玩几个样例可以发现奇数队伍输赢输赢输赢最后是可以平局的
偶数队伍,前n/2赢,n/2平,后面输是可以平局的,2的时候特判一下即可
cpp
#include<cstdio>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<string.h>
#include<queue>
#include<stack>
#include<deque>
#include<vector>
#include<map>
#include<set>
#include <utility>
#include <list>
using namespace std;
typedef long long ll ;
typedef unsigned long long ull ;
#define pii pair<int,int>
const int inf = 0x3f3f3f3f;//106110956
inline int read(){
int x = 0, f = 1;
char ch = getchar();
while(ch < '0' || ch > '9'){
if (ch == '-')
f = -1;
ch = getchar();
}
while(ch >= '0' && ch <= '9'){
x = (x<<1) + (x<<3) + (ch^48);
ch = getchar();
}
return x * f;
}
void print(__int128 num) {
if(num) {
print(num/10);
putchar(num%10+'0');
}
}
int t;
int main(){
scanf("%d",&t);
while(t--){
int n;
scanf("%d",&n);
if(n==2){
printf("0\n");
continue;
}
if(n&1){
for(int i=1;i<=n-1;i++){
int cnt=0;
for(int j=1;j<=n-i;j++){
cnt++;
if(cnt%2==1){
printf("1 ");
}else{
printf("-1 ");
}
}
}
}else{
int now=n/2;
for(int i=1;i<=n-1;i++){
for(int j=1;j<=n-i;j++){
if(j<now){
printf("1 ");
}
if(j==now)printf("0 ");
if(j>now)printf("-1 ");
}
}
}
printf("\n");
}
return 0;
}
远古题目..
题目大概意思是给你n和m,使0<=x<=n&&0<=y<=m,然后让你找最多的点使得任意2个点之间的距离不为整数...
因为题目的n和m的范围很小,可以枚举起点然后在遍历所有点复杂度为(n^4),应该能过。
但是感觉不太靠谱...想了一会没思路看了答案..
发现y=-m/n+m这条线是最优的,起点为(0,m)终点为(n,0)
因为相邻2点的横纵坐标差为1,距离为根号2
这题确实挺离谱的为啥才是1500分题目?
我们可以发现i和n-i-1异或为0(n为2的倍数,这个怎么发现的?)
所以如果最后答案为0的
cpp
if(k==0){
for(int i=0;i<n/2;i++){
printf("%d %d\n",i,n-i-1);
}
考虑答案k<n-1的情况
我们发现k&n-1为k,这其实很好想,n-1的二进制全都是1
然后我们在根据上面构造0
但是n-1和k用了
所以我们不能用0和n-k+1了,又0&n-k+1为0
代码如下:
注意特判因为我们不知道k是否小于n/2,所以i!=k和i!=n-k-1都需要特判
cpp
else if(k<n-1){
printf("%d %d\n",k,n-1);
printf("0 %d\n",n-k-1);
for(int i=1;i<n/2;i++){
if(i!=k&&i != n-k-1){
printf("%d %d\n",i,n-i-1);
}
}
然后就是k=n-1的情况了
我真的吐了怎么这么难构造
我们发现n-1&n-2为n-2,所以我们需要构造1
又1&3=1
所以n-1就构造出来了
又我们n-4和0配不了队了而且n-4&0=0
所以代码如下
cpp
printf("%d %d\n",n-1,n-2);
printf("1 3\n");
printf("%d 0\n",n-4);
for(int i=2;i<n/2;i++){
if(i!=3){
printf("%d %d\n",i,n-i-1);
}
}
然后还有一个特例
4不能组成3
太麻烦了吧...