洛谷P8226题解
作者:互联网
本文同步更新于洛谷博客
前言
目前最优解 \(rank2\)。
题解
我们先模拟一遍算出不放 bomb 时的答案,顺便求出 \(a_i\) 在模 \(k\) 意义下的前缀和。
记为 \(s_i\)。接下来我们 \(O(n)\) 枚举对每个关卡使用 bomb 的答案,假设枚举到第 \(x\) 关。不难发现,我们不选 \(a_x\) 对 \(s_1,s_2,\cdots,s_{x-1}\),没有影响,仅仅会让 \(s_{x+1},s_{x+2},\cdots s_n\) 都减掉 \(a_x\)。所以对于每个 \(x\),答案为 \(\sum\limits_{i=1}^x[s_i\equiv0(\mathrm{mod}\;k)]+\sum\limits_{i=x+1}^n[s_i\equiv a_x(\mathrm{mod}\;k)]\),用个桶记录每种余数出现的次数即可。
Code
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e6+5;
const int maxx=3e5+5;
inline int read()
{
int x=0,f=1;
char ch=getchar();
while(ch<'0'||ch>'9')
{
if(ch=='-')
f=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9')
{
x=(x<<1)+(x<<3)+(ch^48);
ch=getchar();
}
return x*f;
}
int n,m,k,a[maxx],t[maxn],tmp,res,ans;
bool vis[maxx];
int main()
{
n=read(),m=read(),k=read();
for(int i=1;i<=m;i++)
vis[read()]=1;
for(int i=1;i<=n;i++)
{
a[i]=(a[i-1]+read())%k;
if(vis[i])
{
if(!a[i])
ans++;
t[a[i]]++;
}
}
for(int i=1;i<=n+1;i++)
{
tmp=(a[i]-a[i-1]+k)%k;
if(vis[i])
t[a[i]]--;
ans=max(ans,res+t[tmp]);
if(vis[i]&&!a[i])
res++;
}
printf("%d\n",ans);
return 0;
}
标签:ch,洛谷,int,题解,sum,while,P8226,bomb 来源: https://www.cnblogs.com/Gingerhe/p/16029769.html