首页 > 其他分享 >题解 [AGC047C] Product Modulo

题解 [AGC047C] Product Modulo

时间:2022-12-05 13:23:54浏览次数:51  
标签:Product Modulo 题解 void rev cp ll define

显然不能暴力算两两的乘积,而积取模而结果不取模提示我们模数肯定有用。

所有为 \(0\) 的 \(a_i\) 对答案不会产生任何贡献,可以直接删除,下文不再考虑这种情况。同时我们约定,下文的运算(除特殊说明外)均为模 \(P\) 意义下的结果。

设 \(g\) 为 \(P\) 的原根,则每个 \(a_i\) 都可以表示为 \(g^{c_i}\) 的形式,而 \(a_ia_j=g^{c_i+c_j}\)。因此设 \(a\) 中等于 \(g^{i}\) 的数有 \(A_i\) 个,则乘积为 \(g^k\) 的有序数对有 \(\sum\limits_{i+j=k}A_iA_j\) 个,是卷积形式,用 FFT 优化之。

注意根据题意,答案需要去掉所有 \(a_i^2\) 的贡献。

时间复杂度为 \(\Theta(P\log P)\)。

我的代码中 \(g=114513\),当然你也可以用 \(2\) 或者其他原根。

// Problem: C - Product Modulo
// Contest: AtCoder - AtCoder Grand Contest 047
// URL: https://atcoder.jp/contests/agc047/tasks/agc047_c
// Memory Limit: 1024 MB
// Time Limit: 2000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

//By: OIer rui_er
#include <bits/stdc++.h>
#define rep(x,y,z) for(ll x=(y);x<=(z);x++)
#define per(x,y,z) for(ll x=(y);x>=(z);x--)
#define debug(format...) fprintf(stderr, format)
#define fileIO(s) do{freopen(s".in","r",stdin);freopen(s".out","w",stdout);}while(false)
using namespace std;
typedef long long ll;
typedef complex<double> cp;
const ll N = 2e6+5, P = 200003, g = 114513;
const double pi = acos(-1);

ll n, a[N], pw[N], pos[N], cnt[N], rev[N], ans;
cp A[N];
template<typename T> void chkmin(T& x, T y) {if(x > y) x = y;}
template<typename T> void chkmax(T& x, T y) {if(x < y) x = y;}
void change(cp* a, ll n) {
	rep(i, 0, n-1) {
		rev[i] = rev[i >> 1] >> 1;
		if(i & 1) rev[i] |= n >> 1;
	}
	rep(i, 0, n-1) if(i < rev[i]) swap(a[i], a[rev[i]]);
}
void FFT(cp* a, ll n, ll sgn) {
	change(a, n);
	for(ll l = 2, o = 1; l <= n; l <<= 1, o <<= 1) {
		cp w(cos(2.0*pi/l), sgn*sin(2.0*pi/l));
		for(ll i = 0; i < n; i += l) {
			cp now = 1;
			rep(j, i, i+o-1) {
				cp u = a[j], v = a[j + o];
				a[j] = u + v * now;
				a[j + o] = u - v * now;
				now *= w;
			}
		}
	}
	if(sgn == -1) rep(i, 0, n-1) a[i] /= n;
}

int main() {
	pw[0] = 1;
	pos[1] = 0;
	rep(i, 1, P-2) {
		pw[i] = g * pw[i-1] % P;
		pos[pw[i]] = i;
	}
	scanf("%lld", &n);
	rep(i, 1, n) scanf("%lld", &a[i]);
	rep(i, 1, n) if(a[i]) ++cnt[pos[a[i]]];
	rep(i, 0, P-2) A[i] = cnt[i];
	ll m = 1;
	for(; m <= P + P; m <<= 1);
	FFT(A, m, 1);
	rep(i, 0, m-1) A[i] *= A[i];
	FFT(A, m, -1);
	rep(i, 0, 2*(P-2)) ans += (ll)(A[i].real() + .5) * pw[i%(P-1)];
	rep(i, 0, P-2) ans -= cnt[i] * pw[2*i%(P-1)];
	printf("%lld\n", ans / 2);
	return 0;
}

标签:Product,Modulo,题解,void,rev,cp,ll,define
From: https://www.cnblogs.com/ruierqwq/p/agc047c.html

相关文章

  • 能力提升——搜索 题解
    BP5194[USACO05DEC]ScalesS在洛谷,享受coding的快乐AC历程:0pts(MLE)60pts(6AC+4TLE)100pts(AC)虽然题目中说n≤1000,但考虑到“每个砝码的质量至少等于前面两个......
  • JOISC 2022 简要题解
    版刷JOISC的计划就这么结束了。鸽了许多题,懵懵懂懂过来的,兴奋的开始,中途得知省选没了,又鸽了一段时间。好歹是完结了,撒花撒花。总体上题目质量很高,很开心以及荣幸有机会......
  • 题解 [ARC121D] 1 or 2
    诈骗题,竟然评到了\(2784\)的惊人高分(快到红了),来补个题解。题意:有两个可重集\(A,B\),\(B\)初始为\(\varnothing\)。每次从\(A\)中删除一个或两个数,并将它们的和加入......
  • 无知时诋毁原神——题解
    P8880无知时诋毁原神题意简述:给定一个\(0\simn-1\)的排列\(c\)。构造两个同样为\(0\simn-1\)的排列的\(a,b\),满足\(\foralli\in[1,n],c_i=(a_i+b_i)\bmodn\)。如......
  • sql题解--打折日期交叉问题
    题目-打折日期交叉问题现有各品牌优惠周期表(promotion_info)如下,其记录了每个品牌的每个优惠活动的周期,其中同一品牌的不同优惠活动的周期可能会有交叉。promotion_id......
  • win11系统vmware虚拟机报错“不支持嵌套虚拟化”问题解决方案汇总
    一、报错内容vmware0虚拟机中开启虚拟化主机时,报错“Error:Failureinvalidatingvirtualizationcapabilities”[root@localhost~]#rht-vmctlfullresetclassroom......
  • NOIP2022 T1 种花 题解
    Part1吐槽&退役寄考场上唯一AC的题目,T3看错题以为可以删去不止1条边,T4输出没换行,寄。最后喜提100+0+0+0,给我的OI生涯画上了一个不完美的句号。Part2题解题目让统计......
  • CF1709 题解
    比赛链接:https://codeforces.com/contest/1709题解:AB水题//bySkyRainWind#include<cstdio>#include<vector>#include<cassert>#include<cstring>#include<......
  • AtCoder Beginner Contest 280 题解
    A-PawnonaGrid看样例猜题意(要求的是#的数量,直接判断。//If,oneday,Ifinallymanagetomakemydreamsareality...//Iwonder,willyoustillbethere......
  • YACS 2022年11月月赛 乙组 T3 菜单设计 题解
    题目链接上完编程课回来的深夜,更一篇吧。这一题一看数据范围$:18$,阶乘暴力打不了,就是状压。其实我还是比较喜欢状压的,不过这几个月怎么这么多状压?首先:设计状态不难发......