hao
【问题描述】
祖玛是一款曾经风靡全球的游戏,其玩法是:在一条轨道上初始排列着若干个彩色珠子,其中任意三个相邻的珠子不会完全同色。此后,你可以发射珠子到轨道上并加入原有序列中。一旦有三个或更多同色的珠子变成相邻,它们就会立即消失。这类消除现象可能会连锁式发生,其间你将暂时不能发射珠子。
开发商最近准备为玩家写一个游戏过程的回放工具。他们已经在游戏内完成了过程记录的功能,而回放功能的实现则委托你来完成。
游戏过程的记录中,首先是轨道上初始的珠子序列,然后是玩家接下来所做的一系列操作。你的任务是,在各次操作之后及时计算出新的珠子序列。
【输入格式】
第一行是一个由大写字母’A’~’Z’组成的字符串,表示轨道上初始的珠子序列,不同的字母表示不同的颜色。
第二行是一个数字 ,表示整个回放过程共有 次操作。
接下来的 行依次对应于各次操作。每次操作由一个数字 和一个大写字母 描述,以空格分隔。其中, 为新珠子的颜色。若插入前共有 颗珠子,则 表示新珠子嵌入之后(尚未发生消除之前)在轨道上的位序。
【输出格式】
输出共 行,依次给出各次操作(及可能随即发生的消除现象)之后轨道上
NOIP 模拟题 hao
第 3 页 共 6 页
的珠子序列。
如果轨道上已没有珠子,则以“-”表示。
【样例输入】
ACCBA
5
1 B
0 A
2 B
4 C
0 A
【样例输出】
ABCCBA
AABCCBAA
ABBCCBA
-
A
【数据规模与约定】
的数据满足
1<=n<=1000
1<=m<=2000
【解题报告】
想不到第一道模拟题大部分人都没有过。。。。
因为它是一道恶心的模拟。
注意即使一开始出现了相邻的多余3个的球,也只有被同色碰撞才会消失。
一开始可能没有球(所以用gets)。
还有这个插入的写法简直就是黑魔法啊。。。
本着便于理解的原则,请点击http://www.2144.cn/flash/13326.htm
代码如下:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define N 20005
char ch[N],temp[N],e;
int n,size=0,pos;
int res(int a)
{
int head=a,last=a;
char elem;
elem=ch[a];
while(ch[head]==elem&&head) head--;
if(head||ch[head]!=elem) head++;
while(ch[last]==elem&&last<size) last++;
if(last-head>2)
{
strcpy(temp,ch+last);
strcpy(ch+head,temp);
size=size+head-last;
pos=head;
return 1;
}
else return 0;
}
int main()
{
freopen("hao.in","r",stdin);
freopen("hao.out","w",stdout);
gets(ch);
while(ch[size]>='A'&&ch[size]<='Z')size++;
scanf("%d",&n);
while(n--)
{
scanf("%d %c",&pos,&e);
strcpy(temp, ch+pos);
strcpy(ch+pos+1,temp);
ch[pos]=e;size++;
while(res(pos)&&size);
if(size) puts(ch);
else puts("-");
}
return 0;
}
kun
【问题描述】
栈是一种强大的数据结构,它的一种特殊功能是对数组进行排序。例如,借助一个栈,依次将数组1,3,2按顺序入栈或出栈,可对其从大到小排序: 1入栈;3入栈;3出栈;2入栈;2出栈;1出栈。 在上面这个例子中,出栈序列是3,2,1,因此实现了对数组的排序。 遗憾的是,有些时候,仅仅借助一个栈,不能实现对数组的完全排序。例如给定数组2,1,3,借助一个栈,能获得的字典序最大的出栈序列是3,1,2: 2入栈;1入栈;3入栈;3出栈;1出栈;2出栈。 请你借助一个栈,对一个给定的数组按照出栈顺序进行从大到小排序。当无法完全排序时,请输出字典序最大的出栈序列。
【输入格式】
输入共 行。
第一行包含一个整数 ,表示入栈序列长度。
第二行包含 个整数,表示入栈序列。输入数据保证给定的序列是 到n的全排列,即不会出现重复数字。
【输出格式】
仅一行,共 个整数,表示你计算出的出栈序列。
【样例输入】
3
2 1 3
【样例输出】
3 1 2
【数据规模与约定】
对于30% 的数据,1<=n<=1000。
对于 60%的数据, 1<=n<=100000。
对于 100%的数据, 1<=n<=1000000。
【解题报告】
要让字典序尽量大,所以最先输出的数尽量大。
然后乱搞就可以了。
代码如下:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define N 1000005
int n, a[N], stack[N],top=0,nowmax;
bool vis[N];
int main()
{
freopen("kun.in","r",stdin);
freopen("kun.out","w",stdout);
memset(vis,0,sizeof(vis));
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
nowmax=n;
for(int i=1;i<=n;i++)
{
stack[++top]=a[i];
vis[a[i]]=true;
if(nowmax==a[i])
{
top--;
printf("%d ",a[i]);
while(vis[nowmax]) nowmax--;
}
while(a[i+1]<stack[top]&&stack[top]>nowmax)
{
printf("%d ",stack[top]);
top--;
}
}
return 0;
}
nan
【问题描述】
我们有一个序列,现在他里面有三个数 。我们从第三个数开始考虑:
1、第三个数是 ,所以我们在序列后面写 个 ,变成 。
2、第四个数是 ,所以我们在序列后面写 个 ,变成 。
那么你可以看到,这个序列应该是 。
如果我们设一个数 最后出现的位置为 ,那么现在我希望知道 等于多少。
【输入格式】
第一行一个整数 ,代表数据组数。
接下来 行每行一个整数 。
【输出格式】
行,每行一个整数,代表 的值。
【样例输入】
3
3
10
100000
【样例输出】
11
217
507231491
【数据规模与约定】
对于 的数据,1<=x<=1000 。
对于 的数据,1<=x<=1000000 。
对于 的数据, 1<=x<=1e9,1<=T<=2000。
【解题报告】
60%是这么做的:
首先打表找出last和last(last) (这里只写10组):
x ——————1 2 3 4 5 6 7 8 9 10
a[x] —————1 2 2 3 3 4 4 4 5 5
last(x)————1 3 5 8 11 15 19 23 28 33
last(last(x)) ——1 5 11 23 38 62 90 122 167 217
算last(last(x))-last(last(x-1)):
last(last(x))-last(last(x-1)) 1 4 6 12 15 24 28 32 45 50
又可以写成: 1*1 2*2 2*3 3*4 3*5 4*6 4*7 4*8 4*9 5*10
可以看出,后面的数1~10就等于i,而前面的数刚好就是a[x]
于是预处理的时候就将各个分块(a[x]相同的为一块)的left和right保存起来,这样依次用等差序列求和公式就能得出ans了
至于n在中间的情况(如last(last(7)),就用a[4]的right和n(7)做比较,n小则只加上left到n的等差序列,这样就可以过60%的数据
至于100%的数据,要用到前缀和和二分的方法:前缀和求前面连续分块的和,二分求出离n最近的a[rightn].right的编号rightn,
再加上后面的等差序列(同上),可以算出大约第130万个分块的长度超过了1e9,所以二分是可行的。
代码如下:
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
#define N 1400007
#define mod 1000000007
long long n,t;
long long last[N];
long long llst[N];
long long k[N];
struct node
{
long long left,right;
}a[N];
long long temp=2;
int main()
{
freopen("nan.in","r",stdin);
freopen("nan.out","w",stdout);
last[1]=1,last[2]=3;
long long q=2;
a[1].left=a[1].right=1;
a[2].left=2;a[2].right=3;
for(long long i=3;i<=1400000;i++)
{
last[i]=last[i-1]+q;
a[i].right=last[i];
a[i].left=last[i-1]+1;
if(i>=last[temp])
{
q++;temp++;
}
}
for(long long i=1;i<=1400000;i++)
{
k[i]=k[i-1]+(a[i].right-a[i].left+1)*i*(a[i].left+a[i].right)/2%mod;
k[i]%=mod;
}
long long ans=0;
for(scanf("%I64d",&t);t;--t)
{
long long n;scanf("%I64d",&n);
long long l=1,r=1400000;
while(l<=r)
{
long long mid=(l+r)>>1;
if(a[mid].right<n)l=mid+1;
else r=mid-1;
}
ans=k[r];
ans+=(r+1)*(n-a[r].right)*(a[r+1].left+n)/2%mod;
printf("%I64d\n",ans%mod);
}
return 0;
}