AGC, 即 AtCoder Grand Contest 006, 是日本一个在线比赛网站的最高难度级别比赛。AGC 的比赛频率非常低,这也是保证了其题目质量之高。
经常有人“心血来潮,开了一套AGC”,然后发现各种不会做,“感觉智商被AGC摁在地上摩擦”
今天我们来看一套比较古老的 AGC ,AGC 006
A - Prefix and Suffix
这道题目还是送温暖的...
直接枚举长度从
到
最后的
为用第二个字符串填充,剩余空缺从前到后一次用第一个字符串填充
最后验证前
位是否满足第一个字符串即可
由于是从小到大枚举,枚举到可行直接输出答案即可
代码语言:javascript复制#include<bits/stdc .h>
#define LL long long
#define pii pair<int,int>
#define mp make_pair
using namespace std;
int n,m;
char s[110],t[110],p[210];
bool check(int x)
{
for (int i=1;i<=n;i )
if (s[i]!=p[i]) return false;
return true;
}
int main()
{
n=read(s),n=strlen(s 1);
m=read(t);int x=0;
for (int i=n;i<=n n;i )
{
for (int j=1;j<=i-n;j )
p[j]=s[j];
for (int j=1;j<=n;j )
p[(i-n) j]=t[j];
if (check(i)) {print(i),puts("");return 0;}
}
return 0;
}
B - Median Pyramid Easy
这道题目就比较有意思了
首先考虑不可行的情况,显然当
或
的时候是不可行的
因为每一次取的都是三个格子中的中位数,显然到第二行的时候,
或
就消失不见了,更高的行中不可能出现
然后考虑其余情况的构造方法
一种比较通用的构造方法是,最高行为
,我们使得下一行出现至少两个
即可,如下图所示
我们只要保证图中所有的红色格子都是
的话,最后一行一定是
那么,现在,我们只需要构造最后一行的四个格子,使得从第二行开始就在指定位置出现连续的两个
了
这样就比较思博了,
即可
但是我们发现,当
的时候,会有点问题,那么我们对
特判一下,构造
当然,构造的方法不唯一
最后注意特判
的情况,不过我这样构造的话,不会出现问题
代码语言:javascript复制#include<bits/stdc .h>
#define LL long long
#define pii pair<int,int>
#define mp make_pair
using namespace std;
int n,m,a[200010],b[200010];
int main()
{
read(n);read(m);
if (m==1 || m==2*n-1) puts("No");
else
{
puts("Yes");
memset(a,0,sizeof(a));
memset(b,0,sizeof(b));
if (m>2)
{
a[n-1]=m-1,a[n]=m,a[n 1]=m 1,a[n 2]=m-2;
b[m-2]=1,b[m-1]=1,b[m]=1,b[m 1]=1;
}
else
{
a[n-1]=m 1,a[n]=m,a[n 1]=m-1,a[n 2]=m 2;
b[m-1]=1,b[m]=1,b[m 1]=1,b[m 2]=1;
}
int x=1;
for (int i=1;i<n-1;i )
{
while (b[x]==1) x ;
a[i]=x;b[x]=1;
}
for (int i=n 3;i<=2*n-1;i )
{
while (b[x]==1) x ;
a[i]=x;b[x]=1;
}
for (int i=1;i<=2*n-1;i )
print(a[i]),puts("");
}
return 0;
}
C - Rabbit Exercise
这道期望题目一颗赛艇啊
首先考虑对称位置的处理,显然
关于
和
的对称位置分别是
和
考虑兔子
的期望
这样,我们似乎已经得到了
的算法
我们从几何角度来考虑一下这个操作
其实就是
相对于
和
的相对位置发生了变化,
在外面的情况也是如此
再一般的来说,就是
和
的值进行了交换
那么,我们考虑差分,这样,每一次的操作就是对两个数进行交换了
而交换操作是分组进行的,我们可以根据类似快速幂的方式,在
的时间内完成交换
那么总的复杂度就是
代码语言:javascript复制#include<bits/stdc .h>
#define LL long long
#define pii pair<int,int>
#define mp make_pair
using namespace std;
int n,m,a[200010],b[200010];
int main()
{
read(n);read(m);
if (m==1 || m==2*n-1) puts("No");
else
{
puts("Yes");
memset(a,0,sizeof(a));
memset(b,0,sizeof(b));
if (m>2)
{
a[n-1]=m-1,a[n]=m,a[n 1]=m 1,a[n 2]=m-2;
b[m-2]=1,b[m-1]=1,b[m]=1,b[m 1]=1;
}
else
{
a[n-1]=m 1,a[n]=m,a[n 1]=m-1,a[n 2]=m 2;
b[m-1]=1,b[m]=1,b[m 1]=1,b[m 2]=1;
}
int x=1;
for (int i=1;i<n-1;i )
{
while (b[x]==1) x ;
a[i]=x;b[x]=1;
}
for (int i=n 3;i<=2*n-1;i )
{
while (b[x]==1) x ;
a[i]=x;b[x]=1;
}
for (int i=1;i<=2*n-1;i )
print(a[i]),puts("");
}
return 0;
}
int n,m,a[100010],b[100010],ans[100010],c[100010];
LL K;
double x[100010],z[100010];
void Work(LL x)
{
for (;x;x>>=1)
{
if (x&1)
{
for (int i=1;i<n;i )
c[i]=ans[b[i]];
for (int i=1;i<n;i )
ans[i]=c[i];
}
for (int i=1;i<n;i )
c[i]=b[b[i]];
for (int i=1;i<n;i )
b[i]=c[i];
}
}
int main()
{
read(n);
int y;
for (int i=1;i<=n;i )
read(y),x[i]=(double)y;
read(m),read(K);
for (int i=1;i<=m;i )
read(a[i]);
for (int i=1;i<n;i )
b[i]=i,ans[i]=i;
for (int i=1;i<=m;i )
swap(b[a[i]],b[a[i]-1]);
Work(K);
z[1]=x[1];
for (int i=1;i<n;i )
z[i 1]=z[i] (x[ans[i] 1]-x[ans[i]]);
for (int i=1;i<=n;i )
printf("%0.10lfn",z[i]);
return 0;
}
D - Median Pyramid Hard
这道题目似乎是B题的SPJ啊.....
考虑二分答案,假设当前需要验证的答案为
,表示答案
是否成立
那么,根据最下面一行和
的关系,我们可以得到底层的
数列,
表示
我们现在得到了底层的
数列,而题目所给的条件,上一层的一格为
,当且仅当下一层与之对应的三个中至少有两个
现在,符合情况的话,那么就是顶层为
我们可以画画图来分析一下底层的情况,如何向上传导
我们可以发现,当出现连续的两个
的时候,他们所对应的的上面,全部为
那么,这样的情况如何向外拓展呢?
我们发现,当连续的两个
旁边出现隔着一个位置的
的是否,这个全是
的竖行,可以向着隔着一个位置的
的方向拓展一列
那么我们只需要正着反着,各扫一遍
这样一来,我们就可以在
的时间内验证答案了
还有一种比较特殊的情况是,底层不需要出现连续的两个
特判一下
总的时间复杂度是
代码语言:javascript复制#include<bits/stdc .h>
#define LL long long
#define pii pair<int,int>
#define mp make_pair
using namespace std;
inline char nc(){
static char buf[100000],*p1=buf,*p2=buf;
if (p1==p2) { p2=(p1=buf) fread(buf,1,100000,stdin); if (p1==p2) return EOF; }
return *p1 ;
}
inline void read(int &x){
char c=nc();int b=1;
for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1;
for (x=0;c>='0' && c<='9';x=x*10 c-'0',c=nc()); x*=b;
}
inline void read(LL &x){
char c=nc();LL b=1;
for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1;
for (x=0;c>='0' && c<='9';x=x*10 c-'0',c=nc()); x*=b;
}
inline int read(char *s)
{
char c=nc();int len=1;
for(;!(c>='a' && c<='z');c=nc()) if (c==EOF) return 0;
for(;(c>='a' && c<='z');s[len ]=c,c=nc());
s[len ]='