其他分享
首页 > 其他分享> > P8226樱点收集

P8226樱点收集

作者:互联网

P8266

分析题意可以打一个很显然的\(O(n^2)\)暴力

丑陋的赛时代码 \(70pts\)

void work(){
    n=read(),m=read(),k=read();
    for(int i=1;i<=m;++i){
        int x=read();vis[x]=1;
    }
    for(int i=1;i<=n;++i){
        a[i]=read();
    }
    int res=0;
    for(int bomb=0;bomb<=n;++bomb){
        int numsakura=0,ans=0;
        for(int i=1;i<=n;++i){
            if(bomb==i)continue;
            if(numsakura+a[i]>k){
                numsakura=(numsakura+a[i])%k;
                if(numsakura==0 && vis[i]){
                   ans++;
                }
            }
            else if(numsakura+a[i]==k){
                numsakura=0;
                if(vis[i]){
                    ans++;
                }
            }
            else numsakura+=a[i];
        }
        res=max(res,ans);
    }
    printf("%d\n",res);
}
int main(){
    work();
	return 0;
}

接下来考虑动一下脑子

对于每一个关卡,只有在最后在收集完最后一个樱点结界展开时才对答案有贡献,所以我们只考虑恰好的时刻,忽略中间结界展开的过程。

先不考虑放bomb,维护一个前缀和\(sum\),显然有当$ sum[i] \mod k ==0\(时恰好在第i个关卡展开结界,那么可以维护一个\)ans\(数组用来记录不放bomb时前\)i$个关卡的贡献,则有

if(sum[i]%k==0){
	ans[i]=ans[i-1]+vis[i];
}
else ans[i]=ans[i-1];

接下来考虑放bomb,如果在位置\(j\)放了一个\(bomb\),\(1 \rightarrow j-1\)收集到的樱点还是对应的前缀和,也就是说对他们都没有影响,后面收集到的樱点为\(sum[i]-a[j]\)。如果\(sum[i]-a[j] \mod k==0\)才对答案有贡献,但是如果\(O(n^2)\)再算一遍显然不现实。所以我们倒着搞

学过数论的选手都晓得\(sum[i]-a[j] \mod k==0\)实际上为\(sum[i] \equiv a[j] \mod k\),维护一个数组\(rest\),下标为\(x \mod k\), \(rest[i]\)表示在\(i\)关卡之前放了一个bomb\(i\)关卡对答案的贡献,则有

for(int i=n;i>0;--i){//枚举bomb
    res=max(res,ans[i-1]+rest[a[i]%k]);
    rest[sum[i]%k]+=vis[i];
}

然后就结束了

$ \it Speak is nothing ,Show me the Code.$

#include<bits/stdc++.h>
using namespace std;
inline int read(){
    int x=0;char c=getchar();
    while(c<'0'||c>'9')c=getchar();
    while(c>='0'&&c<='9'){
        x=(x<<1)+(x<<3)+(c^'0');c=getchar();
    }
    return x;
}
const int maxn=3e5+5;
const int maxk=1e6+5;
int n,m,k;
int a[maxn];
int sum[maxn];
bool vis[maxn];
int rest[maxk];
int ans[maxn];
void work(){
    n=read(),m=read(),k=read();
    for(int i=1;i<=m;++i){
        int x=read();vis[x]=1;
    }
    for(int i=1;i<=n;++i){
        a[i]=read();
		sum[i]=sum[i-1]+a[i];
	}
    int res=0;
	for(int i=1;i<=n;++i){
		ans[i]=ans[i-1];
        if(sum[i]%k==0){
			ans[i]++;
		}
	}
	for(int i=n;i>0;--i){
		res=max(res,ans[i-1]+rest[a[i]%k]);
		rest[sum[i]%k]+=vis[i];
	}
    printf("%d\n",res);
}
int main(){
    work();
	return 0;
}

标签:bomb,收集,樱点,res,sum,P8226,rest,ans,numsakura
来源: https://www.cnblogs.com/Chano/p/16265407.html