纪中20日c组模拟赛T1 2121. 简单游戏
T1 2121. 简单游戏
(File IO): input:easy.in output:easy.out
时间限制: 1000 ms 空间限制: 262144 KB 具体限制
题目描述
输入
输出
样例输入
4 16
3 9
0 0
样例输出
3 1 2 4
1 3 2 对样例解释:
开始排列: 3 1 2 4
第一次操作:3+1=4 1+2=3 2+4=6
得到: 4 3 6
第二次得到: 7 9
最后就是: 16
数据范围限制
对于30%的数据,保证该组里的每个N都不超过10。
对于100%的数据,保证有每个N不超过20,且每组数据的个数不超过10。
Solution
首先可以发现,对于一个长度为n的排列,经过了n-1次邻项相加后,第i项被加了C(n-1,i)次(二项式定理).
所以可以先预处理杨辉三角形。
Algorithm1
使用next_permutation方便的计算地排列
但是没有剪枝...很慢的
Code1
简单的垃圾代码
#pragma GCC optimize(2)
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<map>
#include<set>
#include<vector>
#include<queue>
#define IL inline
using namespace std;
int tria[][]={
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
};
//triangle
int ans;
int arr[],t,n;
IL int read()
{
char ch;int x=;
ch=getchar();
while(ch<''||ch>'') ch=getchar();
while(ch>=''&&ch<='') x=(x<<)+(x<<)+(ch^),ch=getchar();
return x;
}
int main()
{
freopen("easy.in","r",stdin);
freopen("easy.out","w",stdout);
n=read();
t=read();
do{
for(int i=;i<=n;i++)
arr[i]=i;
do{
ans=;
int i;
for(i=;i<=n&&ans<=t;i++)
ans+=arr[i]*tria[n][i];
if(ans==t&&i>n){
for(int j=;j<=n;j++){
printf("%d",arr[j]);
if(j<n) printf(" ");
}
cout<<endl;
break;
}
}while(next_permutation(arr+,arr+n+));
n=read();
t=read();
}while(n!=||t!=);
return ;
}
Code1
Algorithm2
使用dfs,对每一位进行判断,同时标记use(是否使用过此数)
这比next_permutation好在可以尽情剪枝——只要你能想到
Code2
这是剪枝1:如果当前的和(前depth个数的和)已经超过了t,就跳出。
也可以把
if(sum>t) return;
放到for循环里(这不是废话吗)
可以减少一点分支
按照题解上的说法,这样子只有40分(果然……)
#pragma GCC optimize(2)
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<map>
#include<set>
#include<vector>
#include<queue>
#define IL inline
using namespace std;
int tria[][]={
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
};
int use[];
int ans;
int arr[],t,n;
IL int read()
{
char ch;int x=;
ch=getchar();
while(ch<''||ch>'') ch=getchar();
while(ch>=''&&ch<='') x=(x<<)+(x<<)+(ch^),ch=getchar();
return x;
}
bool succ=;
IL void dfs(int depth,int sum)
{
if(sum>t) return;
if(succ) return;
if(depth==n){
if(sum==t)
{
succ=;
for(int j=;j<=n;j++){
printf("%d",arr[j]);
if(j<n) printf(" ");
}
printf("\n");
}
return;
}
for(int i=;i<=n;i++)
{
if(!use[i])
{
use[i]=;
arr[depth+]=i;
dfs(depth+,sum+i*tria[n][depth+]);
arr[depth+]=;
use[i]=;
}
}
}
int main()
{
// freopen("easy.in","r",stdin);
// freopen("easy.out","w",stdout);
n=read();
t=read();
do{
succ=;
dfs(,);
n=read();
t=read();
}while(n!=||t!=);
return ;
}
Algorithm3
这是剪枝2:
由于杨辉三角形有对称性
比如,枚举到 2 4 1 3 时,其sum(邻项合并后的结果)会与 2 1 4 3 相同
那么可以加入以下判断:
if(depth>(n/) && i<arr[n-depth]) continue;
代码翻译
如果当前要枚举的数即将放的位置超过了总长度的一半,且即将枚举的数值i小于与它关于这个二项式对称的那一项,那就说明这两项如果调换,总值不会发生变化,那么就不考虑这种情况。
这句话真长……
Code3
#pragma GCC optimize(2)
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<map>
#include<set>
#include<vector>
#include<queue>
#define IL inline
using namespace std;
int tria[][]={
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
};
int use[];
int arr[],t,n;
IL int read()
{
char ch;int x=;
ch=getchar();
while(ch<''||ch>'') ch=getchar();
while(ch>=''&&ch<='') x=(x<<)+(x<<)+(ch^),ch=getchar();
return x;
}
bool succ=;
IL void dfs(int depth,int sum)
{
if(succ) return;
if(depth==n){
if(sum==t)
{
succ=;
for(int j=;j<=n;j++){
printf("%d",arr[j]);
if(j<n) printf(" ");
}
printf("\n");
}
return;
}
for(int i=;i<=n;i++)
{
if(!use[i])
{
if(depth>(n/) && i<arr[n-depth]) continue;
if(sum+i*tria[n][depth+]>t) continue;
use[i]=;
arr[depth+]=i;
dfs(depth+,sum+i*tria[n][depth+]);
arr[depth+]=;
use[i]=;
}
}
}
int main()
{
// freopen("easy.in","r",stdin);
// freopen("easy.out","w",stdout);
n=read();
t=read();
do{
succ=;
dfs(,);
n=read();
t=read();
}while(n!=||t!=);
return ;
}
Code3
好的,果然如题解所说,这个剪枝并不能加分。
Algorithm4
这是剪枝3:枚举前,就当前还未使用的数字来讲,可以将它们重新排序,对应还没使用的系数,可以算出已选择的数字不变的情况下,让之后几个数排列组合,再乘以对应系数的和的最大值与最小值。
貌似我讲的不太清楚。
当枚举到第X个数时,剩余的N-X个数,与剩余的N-X个系数一一对应,让大数和大系数相乘,小数和小系数相乘可以得到最大值,让大数和小系数相乘,小数和大系数相乘可以得到最小值,如果剩余的值不在这个范围内,就不要搜下去,这样可以大大优化。
举个栗子
若N=4,T=16:
当枚举arr[1]=1时,剩余16-1*1=15,剩余的未放置的数为2,3,4,剩余的系数为1,3,3,这样最大值为4*3+3*3+2*1=23,最小值为4*1+3*3+2*3=19,都超过了15,所以第一个数不能选1。
Code4
#pragma GCC optimize(2)
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<map>
#include<set>
#include<vector>
#include<queue>
#define IL inline
using namespace std;
int tria[][]={
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
};
int use[];
int tarr[],ttria[];
int arr[],t,n;
IL int read()
{
char ch;int x=;
ch=getchar();
while(ch<''||ch>'') ch=getchar();
while(ch>=''&&ch<='') x=(x<<)+(x<<)+(ch^),ch=getchar();
return x;
}
bool succ=;
IL void dfs(int depth,int sum)
{
if(succ) return;
if(depth==n){
if(sum==t)
{
succ=;
for(int j=;j<=n;j++){
printf("%d",arr[j]);
if(j<n) printf(" ");
}
printf("\n");
}
return;
} int s=;
for(int i=;i<=n;i++)
{
if(use[i]) continue;
tarr[++s]=i;
}
for(int i=depth+;i<=n;i++)
ttria[i-depth]=tria[n][i];
sort(tarr+,tarr+s+);
sort(ttria+,ttria+s+);
int maxs=,mins=;
for(int i=;i<=s;i++)
{
maxs+=tarr[i]*ttria[i];
mins+=tarr[i]*ttria[s-i+];
}
if(t<mins+sum||t>maxs+sum) return; for(int i=;i<=n;i++)
{
if(!use[i])
{
if(depth>(n/) && i<arr[n-depth]) continue;
if(sum+i*tria[n][depth+]>t) continue;
use[i]=;
arr[depth+]=i;
dfs(depth+,sum+i*tria[n][depth+]);
arr[depth+]=;
use[i]=;
}
}
}
int main()
{
// freopen("easy.in","r",stdin);
// freopen("easy.out","w",stdout);
n=read();
t=read();
do{
succ=;
dfs(,);
n=read();
t=read();
}while(n!=||t!=);
return ;
}
Impression
好辛苦呀~~~

纪中20日c组模拟赛T1 2121. 简单游戏的更多相关文章
- 纪中20日c组模拟赛
赛后感想 多写点东西总是好的,但是在最后,算法就不要改动了(就这样我少了10分) 题解 T1 2121. 简单游戏 T2 2122. 幸运票
- 纪中18日c组模拟赛
T2 GMOJ2127. 电子表格 (File IO): input:excel.in output:excel.out 时间限制: 1000 ms 空间限制: 262144 KB 具体限制 ...
- 纪中21日c组模拟赛
AWSL AWSL AWSL AWSL AWSL AWSL AWSL AWSL AWSL AWSL AWSL AWSL AWSL AWSL AWSL AWSL 题解传送 T1 ...
- 纪中20日c组T2 2122. 【2016-12-31普及组模拟】幸运票
2122. 幸运票 (File IO): input:tickets.in output:tickets.out 时间限制: 1000 ms 空间限制: 262144 KB 具体限制 Goto P ...
- 洛谷P1880 [NOI1995]石子合并 纪中21日c组T4 2119. 【2016-12-30普及组模拟】环状石子归并
洛谷P1880 石子合并 纪中2119. 环状石子归并 洛谷传送门 题目描述1 在一个圆形操场的四周摆放N堆石子,现要将石子有次序地合并成一堆.规定每次只能选相邻的2堆合并成新的一堆,并将新的一堆的石 ...
- 纪中23日c组T2 2159. 【2017.7.11普及】max 洛谷P1249 最大乘积
纪中2159. max 洛谷P1249 最大乘积 说明:这两题基本完全相同,故放在一起写题解 纪中2159. max (File IO): input:max.in output:max.out 时间 ...
- 纪中23日c组T3 2161. 【2017.7.11普及】围攻 斐波那契数列
2161. 围攻 (File IO): input:siege.in output:siege.out 时间限制: 1000 ms 空间限制: 262144 KB 具体限制 Goto Prob ...
- 纪中21日c组T2 2117. 【2016-12-30普及组模拟】台风
2117. 台风 (File IO): input:storm.in output:storm.out 时间限制: 1000 ms 空间限制: 262144 KB 具体限制 Goto Proble ...
- 纪中21日c组T1 1575. 二叉树
1575. 二叉树 (File IO): input:tree.in output:tree.out 时间限制: 1000 ms 空间限制: 262144 KB 具体限制 Goto Probl ...
随机推荐
- vuex源码简析
前言 基于 vuex 3.12 按如下流程进行分析: Vue.use(Vuex); const store = new Vuex.Store({ actions, getters, state, mu ...
- ICC中对Skew进行Debug的好工具--Interactive CTS Window
本文转自:自己的微信公众号<集成电路设计及EDA教程> 以后打算交替着推送多种EDA工具的教程而不只是单纯针对某个工具,依次来满足不同粉丝的需求. 这里分享一篇多年之前写的推文,虽然时间 ...
- Spring(六)核心容器 - 注册单例 Bean 实例、SingletonBeanRegistry 简介
前言 上篇文章我们对注册 Bean 的核心类 BeanDefinitionRegistry 进行了讨论,这里的注册 Bean 是指保存 Bean 的相关信息,也就是将 Bean 定义成 BeanDef ...
- Go语言实现:【剑指offer】树的子结构
该题目来源于牛客网<剑指offer>专题. 输入两棵二叉树A,B,判断B是不是A的子结构.(ps:我们约定空树不是任意一个树的子结构) Go语言实现: type TreeNode stru ...
- 【TensorFlow】TensorFlow基础 —— 模型的保存读取与可视化方法总结
TensorFlow提供了一个用于保存模型的工具以及一个可视化方案 这里使用的TensorFlow为1.3.0版本 一.保存模型数据 模型数据以文件的形式保存到本地: 使用神经网络模型进行大数据量和复 ...
- 自定义属性的访问 - Customizing attribute access
自定义属性的访问 - Customizing attribute access 在 python 中, 下列方法可以实现类实例属性 instance.attribute 的 使用,设置,删除. obj ...
- debian 安装xz 命令
# apt install -y xz-utils # xz -d Python-3.6.8.tar.xz # xz -d Python-3.6.8.tar.xz
- windows运行shell脚本
1. 环境变量的理解:快速找到程序并执行,配置在path的目录下有系统环境和用户环境,配置在此的只要目录路径就好,在cmd输入名字就会去此路径找匹配程序执行 2. 将git安装目录下的....\Git ...
- 在windows系统安装nginx
1.下载Nginx,链接:http://nginx.org/en/download.html 2.解压放到自己的磁盘,双击击运行nginx.exe,会有命令框一闪而过,在浏览器上面输入localhos ...
- Day7前端学习之路——多栏布局
该文章主要讨论两栏布局和三栏布局,三栏布局包括很著名的圣杯布局和双飞翼布局 一.两栏布局的七种方法(左边固定,右边自适应) 原理: block水平元素宽度能够跟随父容器调节的流动特性,block级别的 ...