codeforces 487C Prefix Product Sequence

[鏈接] 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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章