机房模拟20180817

T1

当天最难的题目..............

足足三页的题目描述..........

我们可以考虑到对于每一个串来说,串内部满足条件的数字可以先消去,所以我们直接先将串内的数消去,这样可以得到一个新的串

然后我们从两端向中间一个一个枚举数字,只要相等就继续枚举下去,如果说数量达到了k的话就取模并且更新原来的序列

最后就是每个循环剩余长度*(m-1)+仅去掉同一循环的剩余数的个数。(不懂的话自己推一下就好了.....这个公式很简单的.......)

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define LL long long
LL n,m,tot,k,s[100005][2],cnt;
int main()
{
	freopen("guass.in","r",stdin);
	freopen("guass.out","w",stdout);
	std::scanf("%I64d%I64d%I64d",&n,&m,&k);
	for(int i=1;i<=n;i++)
	{
		LL x;
		std::scanf("%I64d",&x);
		if(!cnt||s[cnt][0]!=x)
		{
			s[++cnt][0]=x;
			s[cnt][1]=1;
		}
		else s[cnt][1]++;
		if(s[cnt][1]==k)s[cnt][1]=0,cnt--;
	}
	for(int i=1;i<=cnt;i++)
	{
		tot+=s[i][1];
	}
	int head=1;
	int tail=cnt;
	while(head<tail&&s[head][0]==s[tail][0])
	{
		if(!((s[head][1]+s[tail][1])%k))
		{
			head++;tail--;
		}
		else
		{
			s[head][1]=(s[head][1]+s[tail][1])%k;
			s[tail][1]=0;
			break;
		}
	}
	LL ans=0;
	if(head<tail)
	{
		for(int i=head;i<=tail;i++) ans+=s[i][1];
		ans*=(m-1);
		ans+=tot;
	}
	else if(head==tail)
	{
		if((s[head][1]*m)%k&
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值