[CF487C]Prefix Product Sequence

280 篇文章 1 订阅
这篇博客探讨了寻找使前缀积模n等于0的序列解的数学问题。首先,作者指出当n为1或素数时不成立,而n=4时存在唯一解。接着分析了当n由单一质因数或多个质因数组成时的解法,并给出代码实现。文章最后提供了具体解法和验证过程。
摘要由CSDN通过智能技术生成

题目

传送门 to luogu

思路

我好弱 😢

一、判断无解

n = 1 n=1 n=1 一律不考虑,因为答案就是单个 1 1 1 就完了。

首先 n n n 一定在末尾,因为一旦含有 n n n ,模 n n n 就肯定是 0 0 0 了。那么倒数第二个前缀积就是 ( n − 1 ) ! (n-1)! (n1)! ,这个值就不能为 0 0 0 。什么情况下 ( n − 1 ) ! (n-1)! (n1)! n n n 的倍数呢?

1.单个质因数

假设 n = p q n=p^q n=pq ,其中 p p p 是一个质数。那么 ( n − 1 ) ! (n-1)! (n1)! 中含有的 p p p 的指数为

∑ i = 1 + ∞ ⌊ p q − 1 p i ⌋ \sum_{i=1}^{+\infty}\left\lfloor\frac{p^q-1}{p^i}\right\rfloor i=1+pipq1

显然 i = 1 i=1 i=1 这一项的贡献就已经是 ⌊ p q − 1 − 1 p ⌋ = p q − 1 − 1 \lfloor p^{q-1}-\frac{1}{p}\rfloor=p^{q-1}-1 pq1p1=pq11 了。这玩意儿可能小于 q q q 吗?

显然指数型函数增长的更快。所以 q q q 越大,越不可能实现这一目的。我们不妨手推较小的几个 q q q

  • q = 1 q=1 q=1 时, n n n 就是一个素数,显然 ( n − 1 ) ! ≡ n − 1 ≠ 0 ( m o d n ) (n-1)!\equiv n-1\ne 0\pmod{n} (n1)!n1=0(modn)
  • q = 2 q=2 q=2 时,原不等式等价于 p − 1 < 2 p-1<2 p1<2 ,可知 p = 2 p=2 p=2 。代入知 2 2 = 4 2^2=4 22=4 是一个特殊解,因为 3 ! = 6 3!=6 3!=6 不是 4 4 4 的倍数。
  • q = 3 q=3 q=3 时, p 2 − 1 < 3 p^2-1<3 p21<3 ,已经无法做到了。容易判断, q > 3 q>3 q>3 亦无解。

综上: n n n 的质因数只有一个的时候, n n n 不为素数且 n ≠ 4 n\ne 4 n=4 ( n − 1 ) ! (n-1)! (n1)! n n n 的倍数。

2.多个质因数

不妨设 n = p 1 q 1 p 2 q 2 ⋯ p k q k n=p_1^{q_1}p_2^{q_2}\cdots p_k^{q_k} n=p1q1p2q2pkqk ,其中 p i p_i pi 为质数, q i q_i qi 均不为零。

显然任何一个质因数都是真因子,即 p i q i < n p_i^{q_i}<n piqi<n ,所以 ( n − 1 ) ! (n-1)! (n1)! 中包含了每一个 p i q i p_i^{q_i} piqi 。于是 ( n − 1 ) ! (n-1)! (n1)! n n n 的倍数。

3.综上可得

n n n 必须为素数,或者 n = 4 n=4 n=4 才可能有解。

二、生成一组解

对于 n = 4 n=4 n=4 的情况, ⟨ 1 , 3 , 2 , 4 ⟩ \langle 1,3,2,4\rangle 1,3,2,4 是可以自己手玩出的解。

n n n 是素数怎么办?我在这里卡了 2 h 2h 2h 无果。其实主要是因为我太弱。

答案是 ⟨ 1 , 2 1 , 3 2 , … , n − 1 n − 2 , n ⟩ \left\langle 1,\frac{2}{1},\frac{3}{2},\dots,\frac{n-1}{n-2},n\right\rangle 1,12,23,,n2n1,n 即可。这里的分数可以用逆元转化为一个整数。

显然这里的数字是两两不同的,因为 x x − 1 = 1 + 1 x − 1 \frac{x}{x-1}=1+\frac{1}{x-1} x1x=1+x11 ,如果某两个数字相同,就说明其逆元相等。这可太离谱了。而且这个值也不可能是 1 1 1

代码

#include <cstdio>
#include <iostream>
#include <vector>
using namespace std;
typedef long long int_;
inline int readint(){
	int a = 0; char c = getchar(), f = 1;
	for(; c<'0'||c>'9'; c=getchar())
		if(c == '-') f = -f;
	for(; '0'<=c&&c<='9'; c=getchar())
		a = (a<<3)+(a<<1)+(c^48);
	return a*f;
}
inline void writeint(int x){
	if(x > 9) writeint(x/10);
	putchar((x%10)^48);
}
inline int qkpow(int_ b,int q,int m){
	int ans = 1;
	for(; q; q>>=1,b=b*b%m)
		if(q&1) ans = ans*b%m;
	return ans;
}

const int MaxN = 100005;
int inv[MaxN], ans[MaxN];

int main(){
	int n = readint();
	if(n == 4){
		puts("YES\n1\n3\n2\n4");
		return 0;
	}
	for(int i=2; 1ll*i*i<=n; ++i)
		if(n%i == 0){
			puts("NO"); return 0;
		}
	puts("YES");
	inv[1] = 1;
	for(int i=2; i<n; ++i)
		inv[i] = (0ll+n-n/i)*inv[n%i]%n;
	ans[1] = 1;
	for(int i=2; i<n; ++i)
		ans[i] = 1ll*i*inv[i-1]%n;
	for(int i=1; i<n; ++i)
		printf("%d\n",ans[i]);
	printf("%d\n",n);	
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值