专栏文章
题解:AT_abc392_g [ABC392G] Fine Triplets
AT_abc392_g题解参与者 1已保存评论 0
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 0 条
- 当前快照
- 1 份
- 快照标识符
- @miq9ejp6
- 此快照首次捕获于
- 2025/12/04 01:06 3 个月前
- 此快照最后确认于
- 2025/12/04 01:06 3 个月前
题意
给你一个大小为 的集合 ,求满足 且 且 的三元组 个数。
思路
设集合中某个数 出现的次数为 ,考虑枚举 和 ,则答案为:
其中 ,。
设 ,则原式可以转化为
我们规定 ,然后考虑化简 ,有
不难发现 是一个卷积的形式,带入原式得
因为任意一个在集合中出现的元素 都有 ,故 ,所以最终算出来再统一减去 即可。
设 ,,计算出 的系数再统计答案即可。这里使用NTT来达到 的时间复杂度。
代码
CPP#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=1e6+5,mod=998244353,g=3;//998244353=(2^23)*7*17
int fpow(int n,int k=mod-2)//快速幂
{
int res=1,base=n;
for(;k>0;k>>=1)
{
if((k&1)==1)res=1ll*res*base%mod;
base=1ll*base*base%mod;
}
return res;
}
const int invg=fpow(g);
int rev[N<<2];
void NTT(int*a,int len,bool inv) //NTT
{
for(int i=0;i<len;i++)
if(i<rev[i])swap(a[i],a[rev[i]]);
for(int mid=1;mid<len;mid<<=1)
{
int wn=fpow(inv?invg:g,(mod-1)/(mid<<1));
for(int i=0;i<len;i+=mid<<1)
{
int wk=1;
for(int j=i;j<i+mid;j++,wk=1ll*wk*wn%mod)
{
int x=a[j],y=1ll*wk*a[j+mid]%mod;
a[j]=(x+y)%mod,a[j+mid]=(x-y+mod)%mod;
}
}
}
}
void times(int n,int m,int*a,int*b) //计算多项式相乘的系数
{
int len=1,cnt=0;
while(len<=n+m)len<<=1,cnt++;
for(int i=1;i<len;i++)rev[i]=(rev[i>>1]>>1)|((i&1)<<cnt-1);
NTT(a,len,false),NTT(b,len,false);
for(int i=0;i<len;i++)a[i]=1ll*a[i]*b[i]%mod;
NTT(a,len,true);
for(int i=0;i<len;i++)a[i]=1ll*a[i]*fpow(len)%mod;
}
int a[N<<2],b[N<<2],x[N];
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
int n;
cin>>n;
for(int i=1;i<=n;i++)cin>>x[i],a[x[i]]++,b[x[i]]++;
times(1e6,1e6,a,b);
ll ans=0;
for(int i=1;i<=n;i++)ans+=a[2*x[i]]; //统计答案
cout<<(ans-n)/2;
return 0;
}
相关推荐
评论
共 0 条评论,欢迎与作者交流。
正在加载评论...