[ZJOJ6271]整除(中国剩余定理+原根)

题意

[题目描述]

整除符号为 ∣ | , d ∣ n d|n dn在计算机语言中可被描述为 n % d = = 0 n\% d == 0 n%d==0
现有一算式 n ∣ x m − x n|x^m -x nxmx,给定 n n n, m m m,求 [ 1 , n ] [1,n] [1,n]以内 x x x解的个数。
解可能很大,输出取模 998244353 998244353 998244353

[输入格式]

从文件 d i v i s i o n . i n division.in division.in中读入数据。

其中 n n n的给定方式是由 c c c个不超过 t t t的质数的乘积给出的, c c c t t t的范围会在数据范围中给出。
第一行一个 i d id id表示这个数据点的标号。
多组数据,其中第二行一个整数 T T T表示数据组数。
对于每一组数据:
第一行两个整数 c c c m m m
第二行 c c c个整数,这些整数都是质数,且两两不同,他们的乘积即为 n n n
由于你可以通过输入求出 t t t,输入不再给出。

[输出格式]

输出到文件 d i v i s i o n . o u t division.out division.out中。

对于每组数据输出一行,表示解的个数。

[样例1输入]

0
1
2 3
2 3

[样例1输出]

6

[数据范围与提示]

测试点编号 c ≤ c≤ c t ≤ t≤ t m ≤ m≤ m T ≤ T≤ T
12 1 0 3 10^3 103 2 2 250
22 1 0 3 10^3 103 1 0 9 10^9 10950
32 1 0 2 10^2 102 2 2 210000
41 1 0 4 10^4 104 2 2 250
52 1 0 4 10^4 104 2 2 250
6-810 1 0 4 10^4 104 1 0 9 10^9 10950
9-1050 1 0 4 10^4 104 1 0 9 10^9 10950

题解

x m − 1 ≡ 0 (   m o d   n ) x^{m-1}≡0(\bmod n) xm10(modn)的解的个数,在[1,n-1]范围内就是 g c d ( m − 1 , n − 1 ) gcd(m-1,n-1) gcd(m1,n1)
原问题求 x m ≡ x (   m o d   p 1 p 2 . . . p c ) x^m≡x(\bmod p_1p_2...p_c) xmx(modp1p2...pc)
可以将其化为
{ x m − 1 ≡ 1 (   m o d   p 1 ) x m − 1 ≡ 1 (   m o d   p 2 ) . . . x m − 1 ≡ 1 (   m o d   p c ) \begin{cases} x^{m-1}≡1(\bmod p_1) \\ x^{m-1}≡1(\bmod p_2) \\ ...\\ x^{m-1}≡1(\bmod p_c) \\ \end{cases} xm11(modp1)xm11(modp2)...xm11(modpc)
注意到从每个方程的一个合法解中任取一个乘起来,就能够组成一个原方程合法的解

因此我们就只用算每个方程的解就好了…

而单个方程的解的个数就为 gcd ⁡ ( m − 1 , p − 1 ) + 1 \gcd(m-1,p-1)+1 gcd(m1,p1)+1

乘起来即可。

证明:

我们要求满足 x ∈ [ 1 , p ] x∈[1,p] x[1,p] x m ≡ x (   m o d   p ) x^m≡x (\bmod p) xmx(modp) x x x 的个数。

首先 x = p x=p x=p 一定满足,故不特殊考虑,最后答案 + 1 +1 +1 即可。接下来只考虑 x ∈ [ 1 , p − 1 ] x∈[1,p−1] x[1,p1] 的情况。由于 p p p 为质数,因此 p p p存在一个原根 g g g [ 1 , p − 1 ] [1,p−1] [1,p1]内的任意数在   m o d   p \bmod p modp 意义下都可以表示为 g y g^y gy 的形式。这样,原方程就转化为:

g m y ≡ g y (   m o d   p ) g^{my}≡g^y (\bmod p) gmygy(modp)

根据费马小定理:

m y ≡ y (   m o d   p − 1 ) ⇒ ( m − 1 ) y ≡ 0 (   m o d   p − 1 ) my≡y (\bmod p−1)⇒(m−1)y≡0 (\bmod p−1) myy(modp1)(m1)y0(modp1)

k = gcd ⁡ ( m − 1 , p − 1 ) k=\gcd(m−1,p−1) k=gcd(m1,p1),两边同时除以 kk,得:

m − 1 k y ≡ 0 ( m o d p − 1 k ) \frac{m−1}{k}y≡0 (mod \frac{p−1}{k}) km1y0(modkp1)

由于此时 g c d ( m − 1 k , p − 1 k ) = 1 gcd(\frac{m−1}{k},\frac{p−1}{k})=1 gcd(km1,kp1)=1,因此 y y y 一定有 p − 1 k ∣ y \frac{p−1}{k}|y kp1y。由于 y ∈ [ 0 , p − 2 ] y∈[0,p−2] y[0,p2],显然, p − 1 k \frac{p−1}{k} kp1 的任意小于 k k k 的非负整数倍( 0 ∼ k − 1 0∼k−1 0k1 倍)均满足条件,因此 y y y 共有 k k k 种合法取值。

因此满足 ∑ x = 1 p [ x m ≡ x   m o d   p ] ∑^p_{x=1}[x^m≡x \bmod p] x=1p[xmxmodp] i i i 共有 k + 1 k+1 k+1个。

[来自ImagineC大佬]

实现

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
#define MAXN 10000000
#define LL long long
#define MOD 998244353
int T,n,m;
int gcd(int a,int b){
	return (!b)?a:gcd(b,a%b);
}
int main()
{
	freopen("division.in","r",stdin);
	freopen("division.out","w",stdout);
	scanf("%*d%d",&T);
	while(T--){
		scanf("%d%d",&n,&m);
		LL ans=1;
		for(int i=1;i<=n;i++){
			int x;scanf("%d",&x);
			ans=ans*(gcd(x-1,m-1)+1)%MOD;
		}printf("%lld\n",ans);
	}
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值