题面:

alt

思路:

通过前缀和的思想,从0开始,当前值即为(sum+a[i])%p,用upper_bound查看map中是否有比当前值大的,如果有,那必然是比当前值少了k倍的p,那么起点则为upper出来的值,如果没有,则起点为0,比较当前(sum减去起点处的前缀和值加p)%p是否大于当前最大值,如果是则更换起点终点坐标以及最大值,同时将当前值和坐标存储进map,如此便可找到题目所需的最大值。

代码附下:

void solve() 
{
	ll n,p,sum=0;
	cin>>n>>p;
	map<ll,ll>mp;
	array<ll,3>ans={0,0,0};
	mp[0]=0;
	for(ll i=1;i<=n;i++)
	{
		ll num;
		cin>>num;
		sum=(sum+num)%p;
		auto it=mp.upper_bound(sum);
		if(it==mp.end())it=mp.begin();
		array<ll,3>fff={(sum-it->fs+p)%p,it->sc,i-1};
		ans=max(ans,fff);
		mp[sum]=i;
	}
	cout<<ans[1]<<" "<<ans[2]<<" "<<ans[0];
}
int main()
{
	ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
	ll _=1;
//	cin>>_;
	while(_--)
		solve();
	return 0;
}

如有错误烦请指正谢谢