\(\mathcal{Description}\)

  给定 \(\{a_n\}\),求一个 \(\{b_{n-1}\}\),使得 \(\forall x\in\{a_n\},\exists i,j\in[1,n),b_i+b_j=x\)。输出 \(\{b_{n-1}\}\) 以及对于每个 \(x\) 所应该取的 \(i,j\),或断言不可能。

  \(n\le30\)。

\(\mathcal{Solution}\)

  原来不是构造题啊。(悲

  若 \(a\) 中有偶数 \(2k\),取一个 \(b=k\),然后随便填就好,先特判掉。

  考虑已有了 \(\{b_{n-1}\}\),对于某个 \(b_i+b_j=a_k\),在 \(b_i\) 与 \(b_j\) 之间连接一条权为 \(a_k\) 的边。显然,这些边最终构成了 \(n-1\) 个点 \(n\) 条边的图,必然存在偶环。不妨设环上的 \(b\) 为 \(b_1,b_2,\cdots,b_k\),边权为 \(a_1,a_2,\cdots,a_k\),则应有

\[\begin{cases}b_1+b_2=a_1\\b_2+b_3=a_2\\\dots\\b_k+b_1=a_k\end{cases}
\]

可以钦定 \(b_1=0\),剩下 \(k-1\) 个变量和 \(k\) 个方程,结合环的形状分析发现有解当且仅当 \(\sum_{2\mid i}a_i=\sum_{2\not\mid i}a_i\)。所以用 MiM 在 \(\{a_n\}\) 中找两个等大等和且不交的子集用于构造即可。

  假设 Hash 的复杂度为 \(\mathcal O(1)\),则最终复杂度为 \(\mathcal O(3^\frac{n}{2})\)。

\(\mathcal{Code}\)

  比较卡 qwq。

/* Clearink */

#include <cstdio>
#include <vector>
#include <cassert>
#include <cstdlib> #define rep( i, l, r ) for ( int i = l, rep##i = r; i <= rep##i; ++i )
#define per( i, r, l ) for ( int i = r, per##i = l; i >= per##i; --i ) typedef long long LL; const int MAXN = 30;
const LL INF = 1e11;
int n, half, pwr[20], ans[MAXN + 5];
LL a[MAXN + 5], b[MAXN + 5]; static const int M = 100000037, MAXND = 1.5e7;
int node, head[M], val[MAXND], nxt[MAXND];
LL key[MAXND]; inline int& get( const LL k ) {
int r = head[( k % M + M ) % M], las = -1;
for ( ; r && key[r] != k; r = nxt[las = r] );
if ( r ) return val[r];
if ( !~las ) head[( k % M + M ) % M] = r = ++node;
else nxt[las] = r = ++node;
return key[r] = k, val[r] = -1;
} inline bool count( const LL k ) {
int r = head[( k % M + M ) % M], las = -1;
for ( ; r && key[r] != k; r = nxt[las = r] );
return !!r;
} inline void solve( const int s1, const int s2 ) {
std::vector<int> pos, neg;
rep ( i, 1, half ) {
int f = s1 / pwr[half - i] % 3;
if ( f == 1 ) pos.push_back( i );
else if ( f ) neg.push_back( i );
}
rep ( i, half + 1, n ) {
int f = s2 / pwr[n - i] % 3;
if ( f == 1 ) neg.push_back( i );
else if ( f ) pos.push_back( i );
} assert( pos.size() == neg.size() ); int s = pos.size();
b[1] = 0;
rep ( i, 2, s << 1 ) {
if ( !( i & 1 ) ) {
b[i] = a[pos[( i >> 1 ) - 1]] - b[i - 1];
ans[pos[( i >> 1 ) - 1]] = i - 1;
} else {
b[i] = a[neg[( i >> 1 ) - 1]] - b[i - 1];
ans[neg[( i >> 1 ) - 1]] = i - 1;
}
}
ans[neg[s - 1]] = s << 1;
b[0] = s << 1; rep ( i, 1, n ) if ( !ans[i] ) {
b[++b[0]] = a[i], ans[i] = -b[0];
} puts( "Yes" );
rep ( i, 1, n ) printf( "%lld%c", b[i], i < n ? ' ' : '\n' );
rep ( i, 1, n ) {
if ( ans[i] > 0 ) {
if ( ans[i] < s << 1 ) printf( "%d %d\n", ans[i], ans[i] + 1 );
else printf( "%d 1\n", s << 1 );
} else {
printf( "1 %d\n", -ans[i] );
}
}
} inline void dfs1( const int l, const int r, const int sta, const LL sum ) {
if ( l > r ) return void( get( sum ) = sta );
dfs1( l + 1, r, sta * 3, sum );
dfs1( l + 1, r, sta * 3 + 1, sum + a[l] + INF );
dfs1( l + 1, r, sta * 3 + 2, sum - a[l] - INF );
} inline void dfs2( const int l, const int r, const int sta, const LL sum ) {
if ( l > r ) {
if ( sum && count( -sum ) ) solve( get( sum ), sta ), exit( 0 );
return ;
}
dfs2( l + 1, r, sta * 3, sum );
dfs2( l + 1, r, sta * 3 + 1, sum + a[l] + INF );
dfs2( l + 1, r, sta * 3 + 2, sum - a[l] - INF );
} int main() {
freopen( "problemsetter.in", "r", stdin );
freopen( "problemsetter.out", "w", stdout ); scanf( "%d", &n );
rep ( i, 1, n ) scanf( "%lld", &a[i] ); if ( n == 1 ) {
if ( a[1] % 2 ) puts( "No" );
else printf( "Yes\n%lld\n1 1\n", a[1] / 2 );
return 0;
} rep ( i, 1, n ) if ( !( a[i] % 2 ) ) {
printf( "Yes\n%lld", a[i] / 2 );
rep ( j, 1, n ) if ( i != j ) printf( " %lld", a[j] - ( a[i] / 2 ) );
putchar( '\n' );
rep ( j, 1, n ) {
if ( i == j ) puts( "1 1" );
else printf( "1 %d\n", j + ( j < i ) );
}
return 0;
} half = n + 1 >> 1, pwr[0] = 1;
rep ( i, 1, half ) pwr[i] = pwr[i - 1] * 3; dfs1( 1, half, 0, 0 );
dfs2( half + 1, n, 0, 0 ); puts( "No" );
return 0;
}

Solution -「NOI 模拟赛」出题人的更多相关文章

  1. Solution -「NOI 模拟赛」彩色挂饰

    \(\mathcal{Description}\)   给定一个含 \(n\) 个点 \(m\) 条边的简单无向图,设图中最大点双的大小为 \(s\),则保证 \(s\le6\).你将要用 \(k\) ...

  2. 「CSP-S模拟赛」2019第四场

    「CSP-S模拟赛」2019第四场 T1 「JOI 2014 Final」JOI 徽章 题目 考场思考(正解) T2 「JOI 2015 Final」分蛋糕 2 题目 考场思考(正解) T3 「CQO ...

  3. 「NOIP模拟赛」数位和乘积(dp,高精)

    统计方案数,要么组合数,要么递推(dp)了. 这是有模拟赛历史以来爆炸最狠的一次 T1写了正解,也想到开long long,但是开错了地方然后数组开大了结果100->0 T3看错题本来简单模拟又 ...

  4. 「CSP-S模拟赛」2019第三场

    目录 T1 「POI2007」山峰和山谷 Ridges and Valleys 题目 考场思路(几近正解) 正解 T2 「JOI 2013 Final」 现代豪宅 题目 考场思路(正解) T3 「SC ...

  5. 「CSP-S模拟赛」2019第二场

    目录 T1 Jam的计数法 题目 考场思路(正解) T2 「TJOI / HEOI2016」排序 题目 考场思路(假正解) 正解 T3 「THUWC 2017」随机二分图 题目 考场思路 正解 这场考 ...

  6. 「CSP-S模拟赛」2019第一场

    目录 T1 小奇取石子 题目 考场思路 正解 T2 「CCO 2017」专业网络 题目 考场思路 题解 T3 「ZJOI2017」线段树 题目 考场思路 正解 这场考试感觉很奇怪. \(T1.T2\) ...

  7. 「2018-11-05模拟赛」T5 传送机 解题报告

    5.传送机(sent.*) 问题描述: 黄黄同学要到清华大学上学去了.黄黄同学很喜欢清华大学的校园,每次去上课时总喜欢把校园里面的每条路都走一遍,当然,黄黄同学想每条路也只走一遍. 我们一般人很可能对 ...

  8. 「NOIP模拟赛」Round 3

    Tag 计数+LIS, 二分+ST表, 计数+记搜 A. 改造二叉树 Description 题面 Solution 如果目标序列非严格递增,或者说目标序列是不下降的,那么答案就是 \(n\) 减去最 ...

  9. HHHOJ #153. 「NOI模拟 #2」Kotomi

    抽代的成分远远大于OI的成分 首先把一个点定为原点,然后我们发现如果我们不旋转此时答案就是所有位置的\(\gcd\) 如果要选择怎么办,我们考虑把我们选定的网格边连同方向和大小看做单位向量\(\vec ...

随机推荐

  1. java调用redis的多种方式与心得

    心得: /** * 心得: * 1.连接方式主要有:直连同步,直连事务,直连管道,直连管道事务,分布式直连同步,分布式直连管道, * 分布式连接池同步,分布式连接池管道:普通连接池同步,普通连接池管道 ...

  2. js 动态设置键值对数组 ,类似于 java 的Map 类型

    1.前言 我想设置一个数据  var json = {a1 :1  , a2 :2  , a3 :3  .....} 这样的动态数据 ,怎么写呢? 2.正确写法 var json = []; for ...

  3. 苹果系统 的 qq浏览器 和 qq内置浏览器 无法使用 websocket 的 妥协方案

    没错,就是用不了,js脚本不执行,更别说服务器运行 onopen函数了!!! 怎么办...搞了一天,仍然找不到连接的方法!!! 幸运的是仅仅苹果系统 的无法使用 ,安卓的却可以,奇了怪了 哈皮 ,那我 ...

  4. Feign的应用

    一.定义 可以把Rest的请求进行隐藏,伪装成类似SpringMVC的Controller一样 它集成了ribbon.hystrix.eureka组件 Feign的日志级别需要自定义,因为日志是单独的 ...

  5. 从AAB文件生成APK文件

    开头先说方法 1.下载 bundletool 2.开始生成 java -jar bundletool.jar build-apks --bundle=[aab文件路径(例如:C:\Users\Admi ...

  6. 面试官问,Redis 是单线程还是多线程?我懵了

    我们平时看到介绍 Redis 的文章,都会说 Redis 是单线程的.但是我们学习的时候,比如 Redis 的 bgsave 命令,它的作用是在后台异步保存当前数据库的数据到磁盘,那既然是异步了,肯定 ...

  7. java基础01-03-注释、标识符、数据类型讲解

    java基础01-注释 java中的注释有三种: 单行注释 多行注释 文件注释 public class helloworld { public static void main(String[] a ...

  8. (转)Make 命令

    Make 命令 代码变成可执行文件,叫做编译(compile):先编译这个,还是先编译那个(即编译的安排),叫做构建(build). Make是最常用的构建工具,诞生于1977年,主要用于C语言的项目 ...

  9. SSM项目使用拦截器实现登录验证功能

    SSM项目使用拦截器实现登录验证功能 登录接口实现 public User queryUser(String UserName, String Password,HttpServletRequest ...

  10. 不难懂————Promise对象 + 详解

    1.Promise 的含义 Promise 是异步编程的一种解决方案,比传统的解决方案--回调函数和事件--更合理和更强大.它由社区最早提出和实现,ES6 将其写进了语言标准,统一了用法,原生提供了P ...