因为给定的模数P保证是素数,所以P一定有原根.

根据原根的性质,若\(g\)是\(P\)的原根,则\(g^k\)能够生成\([1,P-1]\)中所有的数,这样的k一共有P-2个.

则\(a_i*a_j(mod\ P)=a_k\) 就可以转化为\(g^i*g^j(mod\ P) = g^{i+j}(mod\ P)=g^k\).

问题转化为了求有多少对有序的<i,j>满足 \((i+j)(mod\ (P-1)) = k\).

求出原根后,对\([1,P-1]\)中的每个数编号, 统计每个编号出现的次数,然后FFT求卷积

要特判0,因为原根不会生成0.所以用总的有序对数-其他不含0的有序对数得到含0的有序对,这是0的答案;超过P-1的数肯定没有符合的有序对.

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int maxn = 2e5+5;
bool notpri[maxn];
int pri[maxn],zyz[maxn];
typedef long long LL; void pre(int N){
notpri[1]=1;
for(int i=2;i<N;++i){
if(!notpri[i]){
pri[++pri[0]]=i;
}
for(int j=1;j<=pri[0] && (LL)i*(LL)pri[j]<N;++j){
notpri[i*pri[j]]=1;
if(i%pri[j]==0){
break;
}
}
}
}
LL Quick_Pow(LL x,LL p,LL mod){
if(!p){
return 1ll;
}
LL res=Quick_Pow(x,p>>1,mod);
res=res*res%mod;
if((p&1ll)==1ll){
res=(x%mod*res)%mod;
}
return res;
}
int FindRoot(int x){/*求素奇数的最小原根,倘若x不是奇数,但是也有原根的话,将质
因子分解改成对phi(x)即可。倘若要求多个原根,直接接着暴力验证即可*/
int tmp=x-1;
for(int i=1;tmp && i<=pri[0];++i){
if(tmp%pri[i]==0){
zyz[++zyz[0]]=pri[i];
while(tmp%pri[i]==0){
tmp/=pri[i];
}
}
}
for(int g=2;g<=x-1;++g){
bool flag=1;
for(int i=1;i<=zyz[0];++i){
if(Quick_Pow((LL)g,(LL)((x-1)/zyz[i]),(LL)x)==1){
flag=0;
break;
}
}
if(flag){
return g;
}
}
return 0;
} const int MAXN = 4e5 + 10;
const double PI = acos(-1.0);
struct Complex{
double x, y;
inline Complex operator+(const Complex b) const {
return (Complex){x +b.x,y + b.y};
}
inline Complex operator-(const Complex b) const {
return (Complex){x -b.x,y - b.y};
}
inline Complex operator*(const Complex b) const {
return (Complex){x *b.x -y * b.y,x * b.y + y * b.x};
}
} va[MAXN * 2 + MAXN / 2], vb[MAXN * 2 + MAXN / 2];
int lenth = 1, rev[MAXN * 2 + MAXN / 2];
int N, M; // f 和 g 的数量
//f g和 的系数
// 卷积结果
// 大数乘积
int f[MAXN],g[MAXN];
vector<LL> conv;
vector<LL> multi;
//f g
void init()
{
int tim = 0;
lenth = 1;
conv.clear(), multi.clear();
memset(va, 0, sizeof va);
memset(vb, 0, sizeof vb);
while (lenth <= N + M - 2)
lenth <<= 1, tim++;
for (int i = 0; i < lenth; i++)
rev[i] = (rev[i >> 1] >> 1) + ((i & 1) << (tim - 1));
}
void FFT(Complex *A, const int fla)
{
for (int i = 0; i < lenth; i++){
if (i < rev[i]){
swap(A[i], A[rev[i]]);
}
}
for (int i = 1; i < lenth; i <<= 1){
const Complex w = (Complex){cos(PI / i), fla * sin(PI / i)};
for (int j = 0; j < lenth; j += (i << 1)){
Complex K = (Complex){1, 0};
for (int k = 0; k < i; k++, K = K * w){
const Complex x = A[j + k], y = K * A[j + k + i];
A[j + k] = x + y;
A[j + k + i] = x - y;
}
}
}
}
void getConv(){ //求多项式
init();
for (int i = 0; i < N; i++)
va[i].x = f[i];
for (int i = 0; i < M; i++)
vb[i].x = g[i];
FFT(va, 1), FFT(vb, 1);
for (int i = 0; i < lenth; i++)
va[i] = va[i] * vb[i];
FFT(va, -1);
for (int i = 0; i <= N + M - 2; i++)
conv.push_back((LL)(va[i].x / lenth + 0.5));
} LL vz[MAXN];
int id[MAXN];
int cnt[MAXN];
int rnk[MAXN];
LL ans[MAXN]; int main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
#endif
pre(maxn-1);
int n,P ;
scanf("%d %d",&n, &P);
int rt = FindRoot(P);
memset(id,0,sizeof(id)); LL idx = 1;
for(int i=0;i<P-1;++i){ //一共只有[0,P-2],P-1个id
id[idx] = i;
rnk[i]= idx;
idx = idx*rt%P;
} for(int i=1;i<=n;++i){
LL tmp;
scanf("%lld",&tmp);
vz[i] = tmp;
tmp%=P;
if(tmp==0) continue; //卷积中不考虑0的贡献
cnt[id[tmp]]++;
} N = M = P;
for(int i=0;i<P-1;++i){
f[i] = g[i] = cnt[i];
} getConv();
int sz = conv.size(); for(int i=0;i<sz;++i){
LL tmp = conv[i];
ans[rnk[i%(P-1)]] += tmp;
} LL tot = (LL)n*n; //全部的枚举可能-不选0之外的组合 = 包含0的组合
for(int i=1;i<P;++i){
tot -= ans[i];
}
ans[0] = tot;
for(int i=1;i<=n;++i){
if(vz[i]>=P) printf("0\n");
else{
printf("%lld\n",ans[vz[i]]);
}
}
return 0;
}

2018秦皇岛ccpc-camp Steins;Gate (原根+FFT)的更多相关文章

  1. 秦皇岛winter camp 总结

    冬令营在秦皇岛自闭了七天,很多题目看了都没有思路,或者是不知道怎么敲代码.我发现图论的题,自己连怎么建树都给忘了,想了半天.还有很多自己从未接触过的算法.在说说课堂上课的情况,大部分时间都是全程懵逼的 ...

  2. UOJ#449. 【集训队作业2018】喂鸽子 min-max容斥,FFT

    原文链接www.cnblogs.com/zhouzhendong/p/UOJ449.html 题解 设 f(i) 表示给 i 只鸽子喂食使得至少一只鸽子被喂饱的期望次数,先 min-max容斥 一下. ...

  3. 2018.12.31 bzoj3771: Triple(生成函数+fft+容斥原理)

    传送门 生成函数经典题. 题意简述:给出nnn个数,可以从中选1/2/31/2/31/2/3个,问所有可能的和对应的方案数. 思路: 令A(x),B(x),C(x)A(x),B(x),C(x)A(x) ...

  4. 2019 秦皇岛CCPC赛后总结

    以前一直想参加ICPC或CCPC的,所以即使得知比赛会打星号,我还是想去. 感觉自己对什么都没有兴趣了,比较渴望找点快乐.. 这场比赛非常强,吉老师和杜老师都来啦,还有岛娘! 有幸要到了签名 滚榜的时 ...

  5. 牛客国庆训练,CCPC Camp DAY1 J 倍增,括号匹配

    https://www.nowcoder.com/acm/contest/201#question 题意:中文不翻译了 解法的个人理解: 对于一个合法的区间$[L,R]$ 1.显然其左括号的匹配位置都 ...

  6. 秦皇岛CCPC的失败总结

    个人状态原因:尤其是我,在比赛前没有很好的做准备,还一直看小说,前两天我们本来应该好好打两场训练赛的时候却没有打,然后一直在玩手机,比赛前一天,我下午就不小心睡着了,然后晚上醒来睡不着第二天的精神状态 ...

  7. 2017 秦皇岛CCPC Balloon Robot (ZOJ 3981)

    题意:给出n个队伍,m个座位,q次A题的队伍与时间,下一行是n个队伍的坐的位置,再下面q行就是第x个队再第y秒A出一道题,然后有一个机器人,开始位置由你选,他每走一步 他就会向右走一格,走到m的时候会 ...

  8. 2018 桂林ccpc现场赛 总结

    Day 0 5个小时的火车,坐的昏昏欲睡.桂林站出来没有地铁,而是出租车排成长队依次上车,也算是某种意义上的地铁吧.到了酒店才发现学校那边又给我们换了,又拖着行李找新的酒店,途中路过一家餐馆,所有人都 ...

  9. 2018 Wannafly summer camp Day8--连通块计数

    连通块计数 描述 题目描述: 小 A 有一棵长的很奇怪的树,他由 n 条链和 1 个点作为根构成,第 i条链有 ai​ 个点,每一条链的一端都与根结点相连. 现在小 A 想知道,这棵长得奇怪的树有多少 ...

随机推荐

  1. 将spark默认日志log4j替换为logback

    1.将jars文件夹下apache-log4j-extras-1.2.17.jar,commons-logging-1.1.3.jar, log4j-1.2.17.jar, slf4j-log4j12 ...

  2. K-mean聚类算法汇聚有用信息——学习笔记

    无监督-无标签 聚类,难点在于评估和调参. k-means最简单实用 基本概念 K值:数据聚成多少类. 质心:各个维度算平均数.Centroid 相似度量:距离来算(欧式距离——直线距离,余弦距离) ...

  3. iOS开发之--png图片编译时报错 (Command /Applications/Xcode.app/Contents/Developer/usr/bin/copypng failed with exit code 1 )

    编译或者运行APP的时候,老是报这个错误:Command /Applications/Xcode.app/Contents/Developer/usr/bin/copypng failed with ...

  4. 基于openssl的https服务配置

    环境: CA服务器:192.168.1.121 WEB服务器: 192.168.1.107 一.在CA服务器上生成自签证书 1.生成根私钥 (umask 077;openssl genrsa -out ...

  5. php 实现Iterator 接口

    <?php class MyIterator implements Iterator{ private $var = array(); public function __construct($ ...

  6. POI读写大数据量EXCEL

    另一篇文章http://www.cnblogs.com/tootwo2/p/8120053.html里面有xml的一些解释. 大数据量的excel一般都是.xlsx格式的,网上使用POI读写的例子比较 ...

  7. SG函数入门

    sg[i]为0表示i节点先手必败. 首先定义mex(minimal excludant)运算,这是施加于一个集合的运算,表示最小的不属于这个集合的非负整数.例如mex{0,1,2,4}=3.mex{2 ...

  8. python线程池ThreadPoolExecutor用法

    线程池concurrent.futures.ThreadPoolExecutor模板 import time from concurrent.futures import ThreadPoolExec ...

  9. Java中的常用方法

    Java中的常用方法 第一章 字符串 1.获取字符串的长度:length() 2.判断字符串的前缀或后缀与已知字符串是否相同    前缀 startsWith(String s).后缀 endsWit ...

  10. webpack4学习笔记(一)

    webpack4 1,安装webpack npm insatll webpack --save-dev //安装最新版本 npm insatll webpack@<version> --s ...