1.K - 比赛 1228 (qingyandark.top)
思维题,读题需要好好审清楚问题。
首先是没理解“编号与自己差值不大于 2”,只需要考虑相邻三个不能重复,每三个一循环,循环的数字可以循环内调整,多个循环的数字排列必须保持一致。
其次是gcd(x,y)=1,就是2,3,5
构成:2 3 5 2 3 5...,2 5 3 2 5 3...,...等等
最后一点就是,n=1的时候需要特判。
思维的分类讨论:
余0: 完整,有6种。
余1:保证余的最小,是2,所以2 3 5、2 5 3,2种情况
余2: 保证余的最小,是2、3,所以是2 3 5、3 2 5两种情况
int n,a[3]={2,5,10};
scanf("%d",&n);
if(n = 1)
puts("2 1");
else
printf("%d %d\n",(n-1)/3*10+a[(n-1)%3],n%3?2:6);
2.B - 比赛 1228 (qingyandark.top)
这道题没有完整思考出解决方案
只思考了需要连续的一段进行计算和,但是应该是在去除这一段后将其左右两段加和,合并成一段--左右两个位置的都是一个属性,这一点没有想到
可以使用vector,然后进行擦除进行操作,也可使用数组。
#include
using namespace std;
typedef long long LL;
const int N=1e5+10;
int n,a,b;
char s[8050];
int val[8050],tot=0;
void input()
{
scanf("%d%d%d%s",&n,&a,&b,s);
int cnt=1;
for(int i=1;imx)
{
mx=val[i];
mxp=i;
}
ans[cur]+=mx; //加入答案
cur^=1;
if(mxp == 1) //在首位置,把该位置权值删去,其余权值左移一格即可
{
for(int i=1;i
3.C - 比赛 1228 (qingyandark.top)
C题待补,set上自动排序不会写,还需要存一下位置。
如下为C题标程
#include
using namespace std;
typedef long long LL;
const int N=1e5+10;
struct node
{
int val,pos;
node(){}
node(int val,int pos):val(val),pos(pos){}
bool operator < (const node& a) const // 按题意对权值和下标进行排序
{
if(val^a.val)return val>a.val;
return pos sval; //存储权值及下标
set spos; //维护下标,递增
void input()
{
scanf("%d%d%d%s",&n,&a,&b,s);
int cnt=1;
for(int i=1;i1)
{
auto itt=spos.find((*it).pos);
if(itt != spos.begin() && itt != ( -- spos.end())) //如果不是首尾元素
{
auto lef=itt; lef -- ; //取左侧指针
auto rig=itt; rig ++ ; //取右侧指针
auto lefval=sval.find(node(val[*lef],*lef)); //返回sval集合找出左侧元素
auto rigval=sval.find(node(val[*rig],*rig)); //返回sval集合找出右侧元素
node nd=*lefval;
nd.val+=(*rigval).val; //合并左右侧元素
val[*lef]+=(*rigval).val;
sval.insert(nd); //插入原集合中
sval.erase(lefval); //并将原本的两相邻元素删除
sval.erase(rigval);
spos.erase(rig); //对于spos集合,删除右侧下标即可
}
spos.erase(itt);
}
sval.erase(it);
}
printf("%d %d\n",ans[0],ans[1]);
}
int main()
{
input();
solve();
return 0;
}