codeforces 487C Prefix Product Sequence

来源:互联网 发布:java用*打印菱形 编辑:程序博客网 时间:2024/06/05 14:08

[链接] http://codeforces.com/problemset/problem/487/C
[sol]

显然,n需要放到最后一个位置上,不然的话后面若干个乘积%p均都为0,与题意相违背。当n为合数时,n

一定能写成一个素数和合数的乘积(4除外),所以除了4以外的合数都没有合法方案。

当n为素数时,令a[i] = i / i-1 % n=i* inv[i - 1](i - 1的逆元);那么形成的序列就是1,2,3,…n-1,0,并且

a[i]=a[j]当且仅当i=j时成立,证明如下:

                    i * inv[i - 1] = j * inv[j - 1]    

同乘(i - 1) * (j - 1)得:

                     i * (j - 1) = j * (i - 1)                             i = j;

关于逆元的求法,此题需要预处理n以内的逆元,一般用O(n)通过下面这个公式来搞

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

证明的话就是先化简,然后同乘i* (p % i)即可。

#include<cstdio>#include<iostream>#include<cstring>#include<cmath>using namespace std;typedef long long ll;const int N = 100000 + 5;ll inv[N];bool ok(int x){    for(int i = 2; i <= sqrt(x); i++)        if (x % i == 0)          return false;    return true;}int main(){    int n;    scanf("%d", &n);    if (n == 1)    {        printf("YES\n1");        return 0;    }    if (n == 4)    {        printf("YES\n1\n3\n2\n4\n");        return 0;    }    if (!ok(n))    {        printf("NO\n");        return 0;    }    inv[1] = 1;    printf("YES\n1\n");    for(int i = 2; i < n; i++)    {        inv[i] = 1LL * (n - n / i) * inv[n % i] % n;        cout<<i * inv[i - 1] % n<<endl;    }    printf("%d\n", n);    return 0;}

[后话]

本题本来想通过两个限制条件的全排列来搞,这样的话复杂度不知道能优化到哪个程度,事实证明

(n<20)时勉强可以出界

#include<cstdio>#include<iostream>#include<cstring>using namespace std;const int N = 100000 + 5;bool f[N], v[N];int q[N];int n;void dfs (int dep,int ans){    if (dep == n - 1)    {        printf("-----------------------------------------\n");        for(int i = 1; i < n; i++)            printf("%d\n", q[i]);        printf("-----------------------------------------\n");        return;    }    for(int i = 1; i < n; i++)        if(!f[i])           {               int t = ans * i % n;               if (v[t] || t>=n)                  continue;               f[i] = true;               v[t] =true;               q[dep + 1] = i;               dfs(dep + 1,t);               f[i] = false;               v[t] = false;               q[dep + 1] = 0;           }}int main(){    v[0] = true;    scanf("%d", &n);    dfs(0,1);    return 0;}
0 0
原创粉丝点击