#乘法逆元#洛谷 3599 Koishi Loves Construction

题目

T a s k 1 Task1 Task1:构造一个长度为 n n n 1 … n 1\dots n 1n的排列,满足其 n n n个前缀和在模 n n n的意义下互不相同
T a k s 2 Taks2 Taks2:构造一个长度为 n n n 1 … n 1\dots n 1n的排列,满足其 n n n个前缀积在模 n n n的意义下互不相同


分析

T a s k 1 Task1 Task1
除了奇数1和偶数,其它都不可构造。
因为 n ∣ n n|n nn,所以 n n n必须为第一个,
1 ∼ n 1\sim n 1n的和为 n ( n + 1 ) 2 \frac{n(n+1)}{2} 2n(n+1),所以如果是非1的奇数,和第一个前缀和模 n n n意义下相同,故无解
答案怎么样,通过一系列的打表可以发现答案可以为 n , 1 , n − 2 , 3 , n − 4 , 5 , … n,1,n-2,3,n-4,5,\dots n,1,n2,3,n4,5,
T a s k 2 Task2 Task2
除了合数4,其它合数都无解。
因为最后的前缀积为 n ! n! n!,所以说 n n n为最后一位,而且 n ∤ ( n − 1 ) ! n\nmid(n-1)! n(n1)!。所以 n n n只能为4或质数(还有特殊的1)
那么除了最后一个为 n n n,每一个答案就是 i i − 1 \frac{i}{i-1} i1i的逆元。


代码

#include <cstdio>
#include <cctype>
#define rr register
using namespace std;
int q,n; long long f[100001];
inline signed iut(){
    rr int ans=0; rr char c=getchar();
    while (!isdigit(c)) c=getchar();
    while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
    return ans;
}

inline bool is_prime(int n)
{
    if(n==2||n==3) return 1;
    if(n%6!=1&&n%6!=5) return 0;
    for(int i=5;i*i<=n;i+=6)
        if(n%i==0 || n%(i+2)==0) return 0;
        return 1;
}
signed main(){
    q=iut();
    if (q&1){
        for (rr int t=iut();t;--t){
            n=iut();
            if (n==1) printf("2 1\n");
            else if (n&1) printf("0\n");
            else{
                printf("2");
                for (rr int i=0;i<(n>>1);++i) printf(" %d %d",n-(i<<1),i<<1|1);
                printf("\n");
            }
        }
    }
    else{
        for (rr int t=iut();t;--t){
            n=iut();
            if (n==1) printf("2 1\n");
            else if (n==4) printf("2 1 3 2 4\n");
               else if (is_prime(n)){
               	       f[1]=1; printf("2 1");
               	       for (rr int i=2;i<=n;++i)
               	           f[i]=f[n%i]*(n-n/i)%n;
               	       for (rr int i=2;i<n;++i)
               	           printf(" %lld",f[i-1]*i%n);
               	       printf(" %d\n",n);
                   }
                   else printf("0\n");
        }
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值