题解-Koishi Loves Construction

前缀知识

质数

逆元

暴搜


Koishi Loves Construction

给定 \(X\),\(T\) 组测试数据,每次给一个 \(n\)。

  1. 如果 \(X=1\),构造一个 \(1\sim n\) 的排列使得前缀和模 \(n\) 互不相同。
  2. 如果 \(X=2\),构造一个 \(1\sim n\) 的排列使得前缀积模 \(n\) 互不相同。

数据范围:\(1\le T\le 10\),\(1\le n\le 10^5\),\(X\in\{1,2\}\)。


属于“思维体操”,做之前会异常兴奋,做之后会只想睡觉。


设序列为 \(a\{n\}\),前缀和/积为 \(sum\{n\}\)。

分类讨论:

\(X=1\)

初步发现:

  1. 不能有区间 \([L,R](L\neq 1)\) 和是 \(n\) 的倍数,否则 \(sum_{L-1}\equiv sum_R\pmod n\)。

  2. 设 \(a_i=n\),必须 \(i=1\),否则 \(sum_i\equiv sum_{i-1}\pmod n\)。

  3. \(\therefore n\in \mathbb{even}\cup {1}\),因为如果 \(n\in \mathbb{odd}\):

\[\sum\limits_{i=1}^{n-1}=\frac{(1+n-1)\times(n-1)}{2}=n\times(\frac{n-1}{2})\equiv 0\pmod n
\]

然后由此判断输出 \(0\&1\),交了一发,\(15\) 分——很明显判断对了。

于是开始打暴力:

#include <bits/stdc++.h>
using namespace std; //&Start
#define lng long long
#define lit long double
#define re register
#define kk(i,n) " \n"[i==n]
const int inf=0x3f3f3f3f;
const lng Inf=0x3f3f3f3f3f3f3f3f; //&Data
const int N=1e5;
int a[N+10],n;
bool vis[N+10],use[N+10];
void dfs(int x,int sm){
if(x==n+1){
for(int i=1;i<=n;i++)
printf("%d%c",a[i],kk(i,n));
return ;
}
for(int i=1;i<=n;i++)
if(!use[i]){
use[i]=1;
if(!vis[(sm+i)%n]){
vis[(sm+i)%n]=1;
a[x]=i;
dfs(x+1,(sm+i)%n);
vis[(sm+i)%n]=0;
}
use[i]=0;
}
} //&Main
int main(){
scanf("%d",&n);
dfs(1,0);
return 0;
} /***
input
6
output
6 1 4 3 2 5
6 2 5 3 1 4
6 4 1 3 5 2
6 5 2 3 4 1
***/

输入 \(6\) 后,看这个输出:

6 1 4 3 2 5

得出规律:

  1. 如果 \(i\in \mathbb{odd}\),\(a_i=n+1-i\)。
  2. 如果 \(i\in \mathbb{even}\),\(a_i=i-1\)。
//&Solve1
void solve1(){
memset(a,0,sizeof a);
memset(sum,0,sizeof sum);
if((n&1)&&(n^1)) return puts("0"),void();
else {
putchar('2'),putchar(' ');
for(int i=1;i<=n;i++)
printf("%d%c",(i&1)?n+1-i:i-1,kk(i,n));
}
}

提交后得到 \(50\) 分,说明对了。

证明:

模 \(n\) 意义下,上述序列可以看成:

0 1 -2 3 -4 5

很明显:

  1. 如果 \(i\in\mathbb{odd}\),\(sum_i\in\{0,-1,-2,...\}\)。
  2. 如果 \(i\in\mathbb{even}\),\(sum_i\in\{1,2,3,...\}\)。

最后在模 \(n\) 意义下还原成正数,

\[\{sum_1,sum_2,...,sum_n\}=\{1,2,...,n\}
\]

\(X=2\)

初步发现:

  1. 不能有区间 \([L,R](L\neq 1)\) 的积 \(\equiv 1\pmod n\)。
  2. 不能有区间 \([L,R](R\neq n)\) 的积 \(\equiv 0\pmod n\)。
  3. \(\therefore a_1=1\)。
  4. \(\therefore a_n=n\)。
  5. 还有如果 \(n|\prod\limits_{i=1}^{n-1}i\) 也不行,很明显。

然后由此判断输出 \(0\&1\),交了一发,\(65\) 分——很明显判断对了

至于序列长什么样,暴力再来一发:

#include <bits/stdc++.h>
using namespace std; //&Start
#define lng long long
#define lit long double
#define re register
#define kk(i,n) " \n"[i==n]
const int inf=0x3f3f3f3f;
const lng Inf=0x3f3f3f3f3f3f3f3f; //&Data
const int N=1e5;
int a[N+10],n;
bool vis[N+10],use[N+10];
void dfs(int x,int sm){
if(x==n+1){
for(int i=1;i<=n;i++)
printf("%d%c",a[i],kk(i,n));
return ;
}
for(int i=1;i<=n;i++)
if(!use[i]){
use[i]=1;
if(!vis[(sm*i)%n]){
vis[(sm*i)%n]=1;
a[x]=i;
dfs(x+1,(sm*i)%n);
vis[(sm*i)%n]=0;
}
use[i]=0;
}
} //&Main
int main(){
scanf("%d",&n);
dfs(1,1);
return 0;
}
/***
input
7
output
1 2 5 6 3 4 7
1 3 4 6 2 5 7
1 4 3 6 5 2 7
1 5 2 6 4 3 7
input
11
output
try it by yourself!
***/

进一步推测:如果 \(n\) 是质数或者 \(n=1\) 或者 \(n=4\),可以构造。

由此判断输出 \(0\& 1\) 提交一发,\(65\) 分,很明显对了(然而没什么用啊。

然后我下了一下数据,竟然发现输出数据只有 \(0\&1\)。

再进一步发现:第二个数只能是 \(2\),没用。

这时看输出(我看了 \(20\) 分钟)

1 2 5 6 3 4 7

//前缀积%n:
1 2 3 4 5 6 0

有一个发现: \(sum_i\equiv i\pmod n\)。

然后我茅塞顿开:可以试试逆元求序列使得 \(sum_i\equiv i\pmod n\)(当然 \(1\) 或 \(4\) 要特判):

void solve2(){
if(np[n]&&(n^1)&&(n^4)) return puts("0"),void();
else {
if(n==1) return puts("2 1"),void();
if(n==4) return puts("2 1 3 2 4"),void();
putchar('2');
for(int i=1,tmp=1,sum=1;i<=n-1;i++){
printf(" %d",tmp);
tmp=1ll*Pow(sum,n-2)*(i+1)%n;
sum=1ll*sum*tmp%n;
}
printf(" %d",n),putchar('\n');
}
}

提交了一发,\(\texttt{AC}\) 了。

证明:

\[\because (i-1)\times a_i\equiv i\pmod n
\]

很明显,对于每个 \(i\),\(a_i\) 是唯一的,只需证明:对于每个 \(a_i\),\(i\) 是唯一的。

反证:假设对于每个 \(a_i\),\(i\) 不唯一,设 \(a_x=a_y=k(x>y)\)。

\[\therefore k(x-1)\bmod n=x,k(y-1)\bmod n=y
\]
\[\therefore k(x-y)\bmod n=(x-y)
\]

因为 \((x-y)\in\{1,2,...,n\}\),所以必定有 \(k(x-y)\bmod n=(x-y+1)\)。

矛盾!故对于每个 \(a_i\),\(i\) 是唯一的。

\(\texttt{code}\)

#include <bits/stdc++.h>
using namespace std; //&Start
#define lng long long
#define lit long double
#define re register
#define kk(i,n) " \n"[i==n]
const int inf=0x3f3f3f3f;
const lng Inf=0x3f3f3f3f3f3f3f3f; //&Data
const int N=1e5;
int X,T,n; //&Solve1
void solve1(){
if((n&1)&&(n^1)) return puts("0"),void();
else {
putchar('2'),putchar(' ');
for(int i=1;i<=n;i++)
printf("%d%c",(i&1)?n+1-i:i-1,kk(i,n));
}
} //&Solve2
bitset<N+10> np;
int p[N+10],cnt;
void Prime(){
np[1]=true;
for(int i=1;i<=N;i++){
if(!np[i]) p[++cnt]=i;
for(int j=1;j<=cnt&&i*p[j]<=N;j++)
np[i*p[j]]=1;
}
}
int Pow(int a,int x){
int res=1;
for(;x;a=1ll*a*a%n,x>>=1)
if(x&1) res=1ll*res*a%n;
return res;
}
void solve2(){
if(np[n]&&(n^1)&&(n^4)) return puts("0"),void();
else {
if(n==1) return puts("2 1"),void();
if(n==4) return puts("2 1 3 2 4"),void();
putchar('2');
for(int i=1,tmp=1,sum=1;i<=n-1;i++){
printf(" %d",tmp);
tmp=1ll*Pow(sum,n-2)*(i+1)%n;
sum=1ll*sum*tmp%n;
}
printf(" %d",n),putchar('\n');
}
} //&Main
int main(){
scanf("%d%d",&X,&T);
if(X==2) Prime();
for(int ti=1;ti<=T;ti++){
scanf("%d",&n);
if(X==1) solve1();
else solve2();
}
return 0;
}

祝大家学习愉快!

题解-Koishi Loves Construction的更多相关文章

  1. 【题解】P3599 Koishi Loves Construction

    [题解]P3599 Koishi Loves Construction \(\mod n\) 考虑如何构造,发现\(n\)一定在第一位,不然不行.\(n\)一定是偶数或者是\(1\),不然 \(n|\ ...

  2. C 洛谷 P3599 Koishi Loves Construction [构造 打表观察]

    题目描述 Koishi决定走出幻想乡成为数学大师! Flandre听说她数学学的很好,就给Koishi出了这样一道构造题: Task1:试判断能否构造并构造一个长度为的的排列,满足其个前缀和在模的意义 ...

  3. 洛谷P3599 Koishi Loves Construction 构造

    正解:构造 解题报告: 传送门! 这题俩问嘛,就分成两个问题港QwQ 就按顺序趴,先港第一问QwQ 首先要发现,n在膜n意义下就是0嘛 那作为前缀和的话显然它就只能放在第一个 然后再想下,发现,如果n ...

  4. P3599 Koishi Loves Construction——构造题

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

  5. 【Luogu3602】Koishi Loves Segments(贪心)

    [Luogu3602]Koishi Loves Segments(贪心) 题面 洛谷 题解 离散区间之后把所有的线段挂在左端点上,从左往右扫一遍. 对于当前点的限制如果不满足显然会删掉右端点最靠右的那 ...

  6. E 洛谷 P3598 Koishi Loves Number Theory[数论]

    题目描述 Koishi十分喜欢数论. 她的朋友Flandre为了检测她和数论是不是真爱,给了她一个问题. 已知 给定和个数,求对取模. 按照套路,呆萌的Koishi当然假装不会做了,于是她来向你请教这 ...

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

    题目描述 Koishi喜欢线段. 她的条线段都能表示成数轴上的某个闭区间.Koishi喜欢在把所有线段都放在数轴上,然后数出某些点被多少线段覆盖了. Flandre看她和线段玩得很起开心,就抛给她一个 ...

  8. luoguP3598 Koishi Loves Number Theory

    题目 题解 等比数列,最后统一除以(x-1)(这里数据都存在逆元....) (不存在逆元可以考虑表示成:x*p^y的pair形式,最后上下把p的次数相减(类似扩展Lucas)) 求:lcm(x^(ai ...

  9. LuoguP3602 Koishi Loves Segments

    题面 n个区间和数轴上的m个关键点 (0<=n,m<=4*1e5,数轴范围 \(-1^7\) ~ \(1^7\))每个关键点有被区间区间覆盖的次数上限,求最多能放多少个区间到数轴上 传送门 ...

随机推荐

  1. Makefile 指定源文件目录 make

    top=$(CURDIR) SRC_DIR=$(top)/src BUILD_DIR=$(SRC_DIR) src=$(wildcard $(SRC_DIR)/*.c) obj=$(patsubst ...

  2. 开发工具之Git(二)

    目录 四.Git安装与配置 (一)安装 (二)配置 (三)创建仓库 五.Git基本命令 六.Git分支 上一篇讲了Git的基本原理,建议没看过的同学先看看,然后这次我们来讲Git的具体操作和指令. 四 ...

  3. oracle的迁移工作

    1.创建新数据库用户 1).创建用户和分配权限 sqlplus / as sysdba create user ENFRC_TEST_GZ_TMP identified by ENFRC_TEST_G ...

  4. python + selenium 搭建环境步骤

    介绍在windows下,selenium python的安装以及配置.1.首先要下载必要的安装工具. 下载python,我安装的python3.0版本,根据你自己的需要安装 下载setuptools ...

  5. HDU100题简要题解(2070~2079)

    HDU2070 Fibbonacci Number 题目链接 Problem Description Your objective for this question is to develop a ...

  6. freshclam

    1 3 * ** /usr/local/clamav/bin/freshclam 定时更新.定时杀毒

  7. 解析MindMapper选项中的鱼骨选项

    MindMapper思维导图可以画鱼骨图,而且完成的相当漂亮,我们可以在选项设置中定义鱼骨图图的默认样式.下面本文就分析了MindMapper选项中可以更改哪些鱼骨图设置. 我们首先打开MindMap ...

  8. MathType可以和哪些Microsoft Office版本一起使用?

    Office类软件可能是我们碰到电脑后,最先接触到的电脑软件了.尤记得,当初的微机课一开始就会讲word和excel的使用,一开始可能学不太明白,但后来越来越频繁的使用office软件,不说offic ...

  9. word选择+快捷键

    统一修改红色章节标题字体:将鼠标放置在章节标题中,前提是各章节标题采用的格式是一样的,单击"选择"-"选择格式相似的文本"即可全部选中进行设置 如下图,章节标题 ...

  10. symfony框架中使用service

    在config文件里面的service.yml写入自己service 1 chat.group_list: //service的名字 2 class: Chat\Service\GroupListSe ...