题解:P10740 [SEERC2020] Divisible by 3
建议先做 P9753 [CSP-S 2023] 消消乐。
对序列
令
最终化简得到:
建议读者自行化简,接着令
于是最终化为:
该贡献可以被
令
方便起见,下面将只与
发现上式化为:
具体实现见代码注释。
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=5e5+5;
int n,a[N],s[N],u[N],ans,t[10][10],x[N];
signed main()
{
clock_t c1=clock();
#ifdef LOCAL
freopen("1.in","r",stdin);
freopen("1.out","w",stdout);
#endif
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
cin>>n;
for(int i=1;i<=n;i++)cin>>a[i];
for(int i=1;i<=n;i++)
{
s[i]=(s[i-1]+a[i])%3;
u[i]=(u[i-1]+a[i]*s[i-1])%3;
x[i]=((u[i]-s[i]*s[i])%3+3)%3;//预处理
}
for(int i=0;i<=n;i++)
{
ans+=t[u[i]][s[i]];//第一维是容易理解的,第二维则是通过 s[r] 除以 3 的余数查询答案
//下面对应 s[r]不同情况更新桶,第二维是 s[r] 除以 3 的余数
t[x[i]][0]++;
t[(s[i]+x[i])%3][1]++;
t[(s[i]*2+x[i])%3][2]++;
}
cout<<ans;
#ifdef LOCAL
cerr<<"Time used:"<<clock()-c1<<"ms";
#endif
return 0;
}