列表

详情


NC13612. 圈圈

描述

shy有一个队列a[1], a[2],…,a[n]。现在我们不停地把头上的元素放到尾巴上。在这过程中我们会得到n个不同的队列,每个队列都是a[k],a[k+1],…,a[n],a[1],…,a[k-1]的形式。在这些队列中,我们可以找到字典序最小的。
shy无聊的时候会给队列的每个元素加一玩。但是为了使得游戏不这么无聊,shy加一以后会给每个元素模m,这样子字典序最小的序列就会变了,生活就变得有趣。
很显然这样子加m次以后,序列会变成原来的样子。所以现在shy想知道,在他没有加一前,加一时,加二时,….,加m-1时字典序最小的序列的第k(和上面的k没有关系)个元素分别是几。

输入描述

第一行三个整数n,m,k表示序列长度,取模的数和要求的序列的第几个元素。 接下来一行n个整数表示初始序列。

输出描述

m个整数表示答案。

示例1

输入:

5 6 3
1 2 1 2 3

输出:

1
2
3
5
5
0

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++14(g++5.4) 解法, 执行用时: 41ms, 内存消耗: 6140K, 提交时间: 2020-09-24 19:25:08

#include<bits/stdc++.h>
using namespace std;


#define ull unsigned long long 

const int N=100005;
int n,m,k;
int a[N];
const ull base=100007;
ull b[N],h[N];
vector<int>v[N];


int solve(int s1,int s2,int add){
	int l=0,r=n,mid,ans=0;
	while(l<=r)
	{
		mid=(l+r)/2;
		if(h[s1]-h[s1+mid]*b[mid]==h[s2]-h[s2+mid]*b[mid])ans=mid,l=mid+1;
		else r=mid-1;
	}
	if(ans==n)return s1;
	return (a[s1+ans]+add)%m<(a[s2+ans]+add)%m?s1:s2;
}

void init(){
	b[0]=1;
	for(int i=1;i<=2*n;i++)b[i]=b[i-1]*base;
	for(int i=2*n-1;i>=0;i--)h[i]=h[i+1]*base+a[i];
}

int main(){
	cin>>n>>m>>k; 
	k--;
		
	for(int i=0;i<n;i++){
		cin>>a[i];
		a[i+n]=a[i];
		v[m-a[i]].push_back(i);
	}
	
	init();
	
	int ans=0;
	for(int i=1;i<n;i++)ans=solve(ans,i,0);
	printf("%d\n",a[ans+k]);
	
	for(int i=1;i<m;i++){
		if(v[i].size()){
			ans=v[i][0];
			for(int j=1;j<v[i].size();j++)ans=solve(ans,v[i][j],i);
		}
		printf("%d\n",(a[ans+k]+i)%m);
	}
	
	return 0;
}

C++11(clang++ 3.9) 解法, 执行用时: 47ms, 内存消耗: 5080K, 提交时间: 2020-08-14 18:26:22

#include<bits/stdc++.h>
using namespace std;

unsigned long long Hash[100005]={0},Power[100005],base=1e9+7;
int n,m,k,a[100005];
vector<int>R[50005];
int get(int x,int y,int t)
{
	int l,r,mid,ans;
	for(l=0,r=n;l<=r;)
	{
		mid=(l+r)>>1;
		if(Hash[x+mid-1]-Hash[x-1]*Power[mid]==Hash[y+mid-1]-Hash[y-1]*Power[mid])ans=mid,l=mid+1;
		else r=mid-1;
	}
	if(ans==n)return x;
	if((a[x+ans]+t)%m<=(a[y+ans]+t)%m)return x;
	return y;
}
int main()
{
    int i,j,ans=1;
    scanf("%d%d%d",&n,&m,&k);
    for(i=1;i<=n;i++)scanf("%d",&a[i]),a[i+n]=a[i],R[m-a[i]].push_back(i);
    for(Power[0]=i=1;i<=2*n;i++)Power[i]=Power[i-1]*base,Hash[i]=Hash[i-1]*base+a[i];
    for(i=2;i<=n;i++)ans=get(ans,i,0);
    printf("%d\n",a[ans+k-1]);
    for(i=1;i<m;i++)
    {
    	if(R[i].size())for(ans=R[i][0],j=1;j<R[i].size();j++)ans=get(ans,R[i][j],i);
    	printf("%d\n",(a[ans+k-1]+i)%m);
	}
    return 0;
}

上一题