P3599 Koishi Loves Construction——构造题

Posted lfri

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P3599 Koishi Loves Construction——构造题相关的知识,希望对你有一定的参考价值。

题目

Task1:试判断能否构造并构造一个长度 $n$ 的 $1...n$ 的排列,满足其 $n$ 个前缀和在模 $n$ 的意义下互不相同

Task2:试判断能否构造并构造一个长度 $n$ 的 $1...n$ 的排列,满足其 $n$ 个前缀积在模 $n$ 的意义下互不相同。

分析

既然考虑原数列很难,就直接考虑前缀和和前缀积。

对于task1:

在模 $n$ 意义下,$\1,2,3,...n\$ 等价于 $ \0,1,-1,2,-2,... \$,我们将它设为前缀和。

其次,我们可以发现 $n$ 必定出现在数列的第一位,否则 $n$ 出现前后的两个前缀和会相等。已知首项,已知前缀和,就可以推出各项。奇数不行。

总结:

当 $n$ 为奇数时,无法构造出合法解(1特判)

当 $n$ 为偶数时,可以构成形如 $n, n-1, 2, n-3, 4...$ 这样的数列

对于Task2:

根据消元法,构造数列 $1,\frac21,\frac32,...,\fracn-1n-2$。

显然,合数没有解,因为其两个两个因子相乘之后,后面取模都为0了。

显然,首项为1,末项为n。

只需证明中间那些数是互不相同的。因为 $\frack+1k = 1 + \frac1k$,当 $n$为质数时,每个元素都有逆元且不相同。

总结:

当 $n$ 为合数,无法构造出合法解(特判4)

当 $n$ 为质数,可以构造形如 $1,\frac21,\frac32,...,\fracn-1n-2,n$.(特判1)

注意开 long long!!!

#include<bits/stdc++.h>
using namespace std;

typedef long long ll;
const int maxn = 100000 + 10;
int task, T;
int n;

void solve1()

    if(n ==  1)
    
        printf("2 1\n");
        return;
    
    if(n&1)
    
        printf("0\n");
        return;
    
    printf("2 %d ", n);
    ll pre = 0;
    //printf("n:%d\n", n);
    for(int i = 1;i < n;i++)
    
        int tmp = ((i&1) == 0 ? 1 : -1) * ((i+1) / 2); //printf("tmp: %d\n", tmp);
        printf("%d", (tmp -pre+n)%n);
        if(i == n-1)  printf("\n");
        else printf(" ");
        pre = tmp;
    


bool is_prime[maxn + 1];
void sieve(int n)

    int m = (int)sqrt(n + 0.5);
    memset(is_prime, true, sizeof(is_prime));
    is_prime[0] = is_prime[1] = false;                //1是特例
    for (int i = 2; i <= m; i++)  if (is_prime[i])
        for (int j = i * i; j <= n; j += i)  is_prime[j] = false;


int inv[maxn];
void init_inv(int n, int mod)

    inv[1] = 1;
    for(int i = 2;i < n;i++)  inv[i] = 1LL * (mod -  mod / i) * inv[mod % i] % mod;  //加mod不改变结果


void solve2()

    if(n == 1)
    
        printf("2 1\n");
        return;
    
    if(n == 4)
    
        printf("2 1 3 2 4\n");
        return;
    
    sieve(n);
    if(!is_prime[n])
    
        printf("0\n");
        return;
    
    init_inv(n, n);
    printf("2 1 ");
    for(int i = 2;i <= n-1;i++)  printf("%d ", 1LL * i * inv[i-1] % n);
    printf("%d\n", n);


int main()

    scanf("%d%d", &task, &T);
    while(T--)
    
        scanf("%d", &n);
        if(task == 1)  solve1();
        else solve2();
    
    return 0;

 

 

 

参考链接:

1. https://oi-wiki.org/basic/construction/

2. https://www.luogu.org/problemnew/solution/P3599

以上是关于P3599 Koishi Loves Construction——构造题的主要内容,如果未能解决你的问题,请参考以下文章

D 洛谷 P3602 Koishi Loves Segments [贪心 树状数组+堆]

P3708 koishi的数学题

P3708 koishi的数学题(因数和)

luogup3708 koishi的数学题

lg3708 koishi的数学题 [数学]

AC自动机 + 矩阵优化 + 期望 --- [BJOI2011]禁忌