cf 487C Prefix Product Sequence 构造+逆元

    数论废 + 脑洞不够大 = = 一上午都没搞出这道题

    学会了一个新的求逆元的姿势

inv[i] = (LL)(n - n / i) * inv[n % i] % n;

    强迫症不行不行的 - - 看到数学题的结论不证明出来就非常不舒服 - - 高考后遗症吗 - -


    按照想到的顺序:

    1. 序列开头一定是1,结尾一定是n

    2.1-4可以手动构造出来

    3.大于4的合数一定无解

         证明:

                   首先由2 可知 (a1a2a3...an-1) mod n == (n - 1)! mod n

                   设n为大于4的合数,设n最小的质因数为k

                       a) 若n / k!=k 那么  n / k <n 

                             所以   (n - 1)! mod n == (n - 1)! mod (n/k * k) == 0;

                        b) 若n/k == k 那么 n == k*k

                             因为 n > 4

                             所以 k > 2

                             所以 k * ( k - 1 ) != k 

                             又因为  k * (k - 1) < n 

                             所以 (n - 1)! mod ((k - 1) * k * k) == 0

                             所以 (n - 1)! mod n == (n - 1)! mod (k * k) = 0

                  综上所述 n为大于4的合数时, (a1a2a3...an-1) mod n ==0 衡成立,显然不符合题意

     4.对于每个质数n 一定可以构造 prefix product sequence 为 [1,2,3,...n-1, 0]

              方法: 假设已经构造好 prefix product sequence 第i-1位 为 i-1 那么要使第 i 位 为 i

                                  只需 a[i] 满足  ((i - 1)*a[i]) mod n == i 

                                  所以 a[i] = i * inv[i-1] mod n

              (因为我比较愚钝 - - 所以纠结了半天这样 a[i] 不会重复吗- -,这里证明一下)


              证明(反证法):

                         假设 1 < i < j < n 且 ((i - 1)*a[i]) mod n == i 且 ((j - 1)*a[i]) mod n == j

                         则 (i - 1) * a[i] == i + k * n   ( k = 0,1,2,3,....)

                              (j - 1) * a[i] == j + k1 * n   ( k1 = 0,1,2,3,....)

                        两式相减

                              (j - i) * a[i] == j-i + (k1 - k) * n

                        移项 

                              (j - i) * (a[i] - 1) == (k1 - k) * n

                        因为 i < j < n 

                        所以 ( j - i ) < n

                        因为 n 为质数

                        所以 (a[i] - 1) mod n == 0

                        由本题题意 a[i] < n 

                        所以 a[i] == 1

                        与 (i - 1) * a[i] mod n == i 矛盾

                        假设不成立,证明结束。


              于是a[i] 不会重复,除了开头的1和结尾的n,与 2 - n-1 一定是一一对应的,也说明对于每个质数,这样一定能构造出符合题意的解

       5.所以就简单了, n == 1-4 的 手动输出一下, n为大于4的合数输出No , 质数则输出 i*inv[i-1] mod n

       

       贴代码

#pragma warning(disable:4996)
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<set>
using namespace std;
typedef long long LL;
const int maxn = 100005;
int n,inv[maxn];
int main() {
	cin >> n;
	if (n <= 3) {
		cout << "YES" << endl;
		for (int i = 1;i <= n;i++) printf("%d\n", i);
	}
	else if(n==4) {
		printf("YES\n1\n3\n2\n4\n");
	}
	else {
		for (int i = 2;i*i <= n;i++) if (n%i == 0) {
			cout << "NO" << endl;
			return 0;
		}
		cout << "YES" << endl;
		cout << 1 << endl;
		inv[1] = 1;
		for (int i = 2;i < n;i++) {
			inv[i] = (LL)(n - n / i) * inv[n % i] % n;
			printf("%d\n", (1LL*i*inv[i - 1])%n);
		}
		cout << n << endl;
	}
	return 0;
}

滚去读初等数论了- -


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值