Typesetting math: 100%

【JZOJ6272】【NOIP提高组A】整除 (division)

题目大意

[1,n]中满足n|xmxx的个数,其中nn=p1p2p3...pc的形式给出。
c50,pi104,m109

解析

这题关键是n的每个质因子都只有一个。

将方程xmx0 (mod n)变为下列方程:

ximxi0 (mod pi) 1ic

列出同余方程组:

xxi (mod pi)

n=p1p2p3...pc,根据中国剩余定理,在[1,n]x有且仅有一个解,即一组合法的xi唯一对应一个x

而将x mod pi又能唯一对应一组xi,因此x的解数就是合法xi的组数,即各合法xi的解数相乘。

问题是如何快速求ximxi0 (mod pi)的解数。

众所周知xm是个积性函数,我们只需要求出[1,pi]内每个质数的m次幂,便可以用线性筛求出每个xim次幂,然后暴力判断,就能AC了,但是有更快的方法。

利用了这样一个结论:xmx0 (mod p)的解数为gcd(m1,p1)+1

证明是这样的:
p是一个质数,因此p必定有原根g,根据原根的性质,[1,p1]内每个数都能用gk mod p表示,原方程可变为:

gmkgk (mod p)

根据费马小定理:

mkk (mod p1)

变形:

(m1)k0 (mod p1)

y=gcd(m1,p1),得到:

m1yk0 (mod p1y)

这时gcd(m1y,p1y)=1,所以p1y|kk是在[0,p2]中的,因此k可以取到p1y[0,y1]倍,所以合法的ky个,对应了合法的x=gk也有y个,但是x=p也是可以的,所以共y+1个合法的x。结论得证。

然后就能以O(logpi)的复杂度解决了,快到飞起。

Code

#include <cstdio>

typedef long long ll;
const ll P = 998244353;

ll gcd(ll a, ll b) { return b ? gcd(b, a % b) : a; }

int T, c;
ll p, m, ans;

int main()
{
	freopen("division.in", "r", stdin);
	freopen("division.out", "w", stdout);
	scanf("%*d%d", &T);
	while (T--)
	{
		scanf("%d%lld", &c, &m);
		ans = 1;
		for (int i = 1; i <= c; i++) scanf("%lld", &p), ans = ans * (gcd(m - 1, p - 1) + 1) % P;
		printf("%lld\n", ans);
	}
	return 0;
}

作者:zjlcnblogs

出处:https://www.cnblogs.com/zjlcnblogs/p/11299900.html

版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。

posted @ 2019-08-04 21:38  gz-gary  阅读(171)  评论(0)    收藏  举报
编辑推荐:
· 一个 java 空指针异常的解决过程
· 揭开 SQL Server 和 PostgreSQL 填充因子的神秘面纱
· 没有调度器的协程不是好协程,零基础深入浅出 C++20 协程
· 别做抢活的导演:代码中的抽象层次原则
· 从 Redis 客户端超时到 .NET 线程池挑战
阅读排行:
· dotnetty 内存泄漏的BUG修复了
· 20250709 - GMX V1 攻击事件: 重入漏洞导致的总体仓位价值操纵
· Apipost 的AI功能真的还不错啊!建议后端开发和测试人员了解
· 面试官:如何实现大模型连续对话?
· MoneyPrinterTurbo – 免费开源的AI短视频生成工具
more_horiz
keyboard_arrow_up light_mode palette
选择主题
点击右上角即可分享
微信分享提示