首页 > 其他分享 >AtCoder Beginner Contest 335 G Discrete Logarithm Problems

AtCoder Beginner Contest 335 G Discrete Logarithm Problems

时间:2024-01-13 19:35:43浏览次数:31  
标签:Logarithm AtCoder typedef Beginner pmod ll long define equiv

洛谷传送门

AtCoder 传送门

考虑若我们对于每个 \(a_i\) 求出来了使得 \(g^{b_i} \equiv a_i \pmod P\) 的 \(b_i\)(其中 \(g\) 为 \(P\) 的原根),那么 \(a_i^k \equiv a_j \pmod P\) 等价于 \(kb_i \equiv b_j \pmod{P - 1}\),有解的充要条件是 \(\gcd(b_i, P - 1) \mid b_j\)。

显然我们不可能对于每个 \(a_i\) 都求出来 \(b_i\)。注意到我们只关心 \(c_i = \gcd(b_i, P - 1)\),而 \(c_i\) 为满足 \(a_i^{c_i} \equiv 1 \pmod P\) 的最小正整数。若求出 \(c_i\) 则等价于统计 \(c_i \mid c_j\) 的对数。于是问题变成求出 \(c_i\)。

因为我们一定有 \(a_i^{P - 1} \equiv 1 \pmod P\),所以 \(c_i\) 一定为 \(P - 1\) 的因数。所以我们初始令 \(c_i = P - 1\),然后对 \(P - 1\) 分解质因数,依次让 \(c_i\) 试除 \(P - 1\) 的每个质因子,判断除完后是否还有 \(a_i^{c_i} \equiv 1 \pmod P\) 即可。这部分复杂度大概是 \(O(n \log^2 P)\) 的。

问题还剩下统计 \(c_i \mid c_j\) 的对数。因为 \(c_i\) 为 \(P - 1\) 的因数,所以我们可以做一遍 Dirichlet 后缀和求出 \(f_x\) 表示满足 \(x \mid c_i\) 的 \(i\) 的个数。最后遍历 \(c_i\) 统计即可。

总时间复杂度大概是 \(O(n \log^2 P + m \log m \log P)\),其中 \(m\) 为 \(P - 1\) 因数个数。

code
// Problem: G - Discrete Logarithm Problems
// Contest: AtCoder - AtCoder Beginner Contest 335 (Sponsored by Mynavi)
// URL: https://atcoder.jp/contests/abc335/tasks/abc335_g
// Memory Limit: 1024 MB
// Time Limit: 5000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#include <bits/stdc++.h>
#define pb emplace_back
#define fst first
#define scd second
#define mkp make_pair
#define mems(a, x) memset((a), (x), sizeof(a))

using namespace std;
typedef long long ll;
typedef __int128 lll;
typedef double db;
typedef unsigned long long ull;
typedef long double ldb;
typedef pair<ll, ll> pii;

const int maxn = 200100;

ll n, m, a[maxn], tot, T, c[maxn], tt, f[maxn];
pii b[maxn];

inline ll qpow(ll b, ll p, const ll &mod) {
	ll res = 1;
	while (p) {
		if (p & 1) {
			res = (lll)res * b % mod;
		}
		b = (lll)b * b % mod;
		p >>= 1;
	}
	return res;
}

void solve() {
	scanf("%lld%lld", &n, &m);
	ll x = m - 1;
	for (ll i = 1; i * i <= x; ++i) {
		if (x % i) {
			continue;
		}
		c[++tt] = i;
		if (i * i != x) {
			c[++tt] = x / i;
		}
	}
	sort(c + 1, c + tt + 1);
	for (ll i = 2; i * i <= x; ++i) {
		if (x % i == 0) {
			ll cnt = 0;
			while (x % i == 0) {
				x /= i;
				++cnt;
			}
			b[++tot] = mkp(i, cnt);
		}
	}
	if (x > 1) {
		b[++tot] = mkp(x, 1);
	}
	for (int i = 1; i <= n; ++i) {
		scanf("%lld", &a[i]);
		ll x = m - 1;
		for (int j = 1; j <= tot; ++j) {
			for (int _ = 0; _ < b[j].scd; ++_) {
				if (qpow(a[i], x / b[j].fst, m) == 1) {
					x /= b[j].fst;
				}
			}
		}
		a[i] = x;
		++f[lower_bound(c + 1, c + tt + 1, a[i]) - c];
	}
	for (int i = 1; i <= tot; ++i) {
		for (int j = tt; j; --j) {
			if (c[j] % b[i].fst) {
				continue;
			}
			ll x = lower_bound(c + 1, c + tt + 1, c[j] / b[i].fst) - c;
			f[x] += f[j];
		}
	}
	ll ans = 0;
	for (int i = 1; i <= n; ++i) {
		ans += f[lower_bound(c + 1, c + tt + 1, a[i]) - c];
	}
	printf("%lld\n", ans);
}

int main() {
	int T = 1;
	// scanf("%d", &T);
	while (T--) {
		solve();
	}
	return 0;
}

标签:Logarithm,AtCoder,typedef,Beginner,pmod,ll,long,define,equiv
From: https://www.cnblogs.com/zltzlt-blog/p/17962796

相关文章

  • AtCoder Beginner Contest 335 (Sponsored by Mynavi)
    AtCoderBeginnerContest335(SponsoredbyMynavi)A-2023代码:#include<bits/stdc++.h>usingnamespacestd;usingll=longlong;usingpii=pair<ll,ll>;#definefifirst#definesesecondvoidsolve(){strings;cin>>s;......
  • AtCoder Beginner Contest 335 总结
    ABC335总结A.202<s>3</s>翻译给你一个由小写英文字母和数字组成的字符串\(S\)。\(S\)保证以2023结尾。将\(S\)的最后一个字符改为4,并打印修改后的字符串。分析两种做法:直接把最后一个字符改为4,然后输出。输出前\(n\)个字符后输出4。code#include<bits/stdc......
  • AtCoder Beginner Contest 295
    B-Bombsd难度:⭐题目大意给定一个n*m的网格,其中'.'表示空白,'#'表示障碍物,数字x表示此处有一个炸弹,会将附近曼哈顿距离小于等于x的格子都变成空白;问所有炸弹爆炸后的网格;解题思路数据范围很小,暴力即可;神秘代码#include<bits/stdc++.h>#definei......
  • AtCoder Regular Contest 167 C MST on Line++
    洛谷传送门AtCoder传送门我是傻逼。很平凡的一个计数。但是不会啊。怎么会是呢。考虑Kruskal求解MSTonLine问题。我们可以想到统计边权\(=a_i\)的出现次数。然后又可以容斥转化成统计边权\(\lea_i\)的出现次数,设其为\(f_i\)。考虑求\(f_i\)。就相当于把\(p\)......
  • AtCoder Beginner Contest 334
    B-ChristmasTrees难度:⭐⭐题目大意小莫从坐标轴的某个位置n种了一棵树,并且每隔m米就再种一棵树,注意是双向的,两边都种;给定一个区间,问这个区间中有多少棵树;解题思路我们可以让区间的边界都减去n,这样区间中的树都位于坐标km上;然后我们把边界都平移到正......
  • AtCoder Beginner Contest 复盘合集
    AtCoderBeginnerContest复盘合集修改链接2023.12.6ABC312VP(OI赛制)这次的ABC相对比较难:红橙黄黄蓝绿绿,Ex(蓝)AlinkB稍微麻烦一点。linkC很水,直接Sort一遍即可。linkD稍微思考,可以得出一个DP,准确来说不太像DPlink【警钟长鸣】我非常的弱智,\(n<=3000\)赛时写......
  • AtCoder Regular Contest 168 F Up-Down Queries
    洛谷传送门AtCoder传送门貌似是第三道问号题?感觉前面这个转化不是人能想到的。。。考虑维护\(y\)的差分序列。更进一步地,我们类比slopetrick,维护一个可重集,里面有\(y_{i+1}-y_i\)个\(i\)(为了方便我们让每次操作时\(y_{m+1}\)加\(1\))。那么一次操作就相当于,插......
  • atcoder
    DPABC275EABC274DABC274EABC271EABC270DABC266D状态机模型ABC265Emap存状态+步骤型遍历(注意DP顺序)+复杂度证明ABC262D关于数字的DP,将一类数字分成一个状态加粗样式ABC261D没啥好说的看题目写DPABC253E关于数字的DPABC251E状态机DPABC197E在一维轴上行走的DP......
  • atcoder补题计划
    DPABC275EABC274DABC274EABC271EABC270DABC266D状态机模型ABC265Emap存状态+步骤型遍历(注意DP顺序)+复杂度证明ABC262D关于数字的DP,将一类数字分成一个状态加粗样式ABC261D没啥好说的看题目写DPABC253E关于数字的DPABC251E状态机DPABC197E在一维轴上行走的DP......
  • AtCoder_abc334
    AtCoder_abc334A-ChristmasPresent题目描述输入两个数\(B,G(B\neqG)\),若\(B\)大,输出Bat,否则输出Glove。解题思路无Code//Problem:A-ChristmasPresent//Contest:AtCoder-UNIQUEVISIONProgrammingContest2023Christmas(AtCoderBeginnerContes......