题解-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. kafak ack应答机制

    ack 应答机制 对于某些不太重要的数据,对数据的可靠性要求不是很高,能够容忍数据的少量丢失, 所以没必要等 ISR 中的 follower 全部接收成功. 所以 Kafka 为用户提供了三种可靠性级 ...

  2. c++实现split

    #include<iostream> #include<vector> #include<algorithm> #include<string> usi ...

  3. Flink处理函数实战之三:KeyedProcessFunction类

    欢迎访问我的GitHub https://github.com/zq2599/blog_demos 内容:所有原创文章分类汇总及配套源码,涉及Java.Docker.Kubernetes.DevOPS ...

  4. 一个Wpf的开发框架

    引言 本框架使用Prism做MVVM,优点咱就不说了,主要了容器注入,消息和DI,比自己写省很多事.网上有很多标准的MVVM的使用方法,但是没有形成一个系统级的框架.本框架从登录到具体业务的使用,还有 ...

  5. 企业级工作流解决方案(十一)--集成Abp和ng-alain--权限系统服务

    权限系统主要定义为管理员增删改查权限数据,直接读取数据库,权限系统服务主要定义为供其他系统调用的权限验证接口,定义为两个不同的微服务. 权限系统有一个特点,数据变动比较小,数据量本身并不是很大,访问量 ...

  6. Java IDEA 根据mybatis-generator-core自动生成代码支持sqlserver获取备注(二)

    mybatis generator代码生成虽然好用,但是好像不支持sqlserver获取备注信息,这里我主要分享mybatis generator改写后支持sqlserver获取备注信息,mysql以 ...

  7. Pytest学习(十一)- 失败重跑插件pytest-rerunfailures的使用

    环境依赖 Python 3.5, 最高 3.8, or PyPy3 pytest 5.0或更高版本 插件安装 pip3 install pytest-rerunfailures -i http://p ...

  8. LGOJ3101 [USACO14JAN]滑雪等级Ski Course Rating

    LGOJ3101 [USACO14JAN]滑雪等级Ski Course Rating [问题描述] The cross-country skiing course at the winter Mool ...

  9. C#设计模式-桥接模式(Bridge Pattern)

    引言 例如我有好几个项目,需要外包出去做各种类型的测试,不同的公司基础费用不同,不同的测试类型价格也是不同的.此时不同的项目选择不同的公司和不同类型的测试进行测试价格都是不同的.于是我们可以创建一个项 ...

  10. .NET使用AutoResetEvent实现多线程打印奇偶数

    AutoResetEvent 类 (System.Threading) | Microsoft Docs 定义 命名空间: System.Threading 程序集: mscorlib.dll, Sy ...