因为给定的模数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. 选择LoadRunner Protocol的两大定律

    选择LoadRunner Protocol的两大定律 确定性能测试脚本录制时使用的协议类型经常是一个容易引起误会的问题.很多刚刚接触到性能测试的同行常常会想当然地根据开发语言等来决定协议的选取,导致录 ...

  2. 【OpenWRT】网络配置

    cd /etc/config vim network vim wireless cd /etc/init.d/network

  3. eclipse中打开含有汉字的properties文件显示乱码

    http://blog.csdn.net/wangjun5159/article/details/46965831

  4. python入门(十):XML和JSON解析

    一.python解析XML 1.xml.dom.*模块,它是W3C DOM API的实现,若需要处理DOM API则该模块很适合,注意xml.dom包里面有许多模块,须区分它们间的不同: 2.xml. ...

  5. POJ 3468 A Simple Problem with Integers(线段树功能:区间加减区间求和)

    题目链接:http://poj.org/problem?id=3468 A Simple Problem with Integers Time Limit: 5000MS   Memory Limit ...

  6. android硬件返回

    1.第一种 @Override    public boolean onKeyUp(int keyCode, KeyEvent event) {        //点击回退键        if(Ke ...

  7. Keil调试程序如何查看变量

    第一个问题:调试时候想实时查看某一变量变化? view 菜单下的 watch windows,全局变量才能查看 比如要查看u8 adcx的值变化,如下: 全速运行后,如下: 无法查看!什么问题? 该变 ...

  8. 教你在Ubuntu上体验Mac风格

    导读 老实说,我是个狂热的 Ubuntu 迷,我喜欢 Ubuntu 默认的 Unity 主题样式外观.此外,还有很多关于 Ubuntu 14.04 的漂亮图标主题样式 可用来美化默认的外观.但正如我上 ...

  9. 深度解析Objective-C笔试题

    2011-08-11 17:39 佚名 互联网 字号:T | T 本文介绍的是Objective-C笔试题,先来问一个,为什么很多内置类如UITableViewController的delegate属 ...

  10. mysql 容灾 灾备 备份

    一.数据备份 1.使用mysqldump命令备份 mysqldump命令将数据库中的数据备份成一个文本文件.表的结构和表中的数据将存储在生成的文本文件中. mysqldump命令的工作原理很简单.它先 ...