纪中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 ...
随机推荐
- 20190708三人开黑CF模拟赛
7月8号晚上8点和两位巨佬开了一场虚拟cf: [Helvetic Coding Contest 2018 online mirror (teams allowed, unrated)] 我这么蔡,只A ...
- String、StringBuilder、StringBuffer区别
=====================================String=================================★1.它在java.lang包中.String类 ...
- SASS用法入门
本文参考了 阮一峰 老师对 SASS 用法的讲解. 学过 CSS 的人都知道,它不是一种编程语言,在日常的开发中,经常要写大量的 css 代码,有很多的重复代码,效率很低.Sass 是一个 CSS 的 ...
- selenium控制浏览器操作
selenium控制浏览器操作 控制浏览器有哪些操作? 控制页面大小 前进.后退 刷新 自动输入.提交 ........ 控制页面大小,实例: # -*- coding:utf-8 -*- from ...
- finished with exit code -1073740791 (0xC0000409)解决方案
1.在用keras框架跑NER的train时,而且只是在用了keras_contrib.layers的CRF时出现问题: 遇到无错跳出finished with exit code -10737407 ...
- 吴恩达deepLearning.ai循环神经网络RNN学习笔记_没有复杂数学公式,看图就懂了!!!(理论篇)
本篇文章被Google中国社区组织人转发,评价: 条理清晰,写的很详细! 被阿里算法工程师点在看! 所以很值得一看! 前言 目录: RNN提出的背景 - 一个问题 - 为什么不用标准神经网络 - RN ...
- JSON Hijacking实战利用
0×01漏洞的挖掘 一般挖掘的过程中,burpsuite代理的History做寻找,过滤多余不可能存在漏洞的一些链接,如下图所示: 我们在返回包中json格式发现了如下的敏感信息(用户Id,用户名,用 ...
- Idea生成代码段
使用快捷键(ctrl+alt+s)找到:从idea的菜单File->Settings->Editor->Live Templates 先添加Template Group,然后添加Li ...
- 基于HttpURLConnection的接口调用,支持GET&POST
单位要做一个多级部署平台,大概意思就是一级系统可以监控下属地域的数据也可管理本地的数据.之前做短信猫用过httpClient请求,与此大同小异.封装了一个两种请求方式的工具类. package com ...
- Java的七大排序
一.各个算法的时间复杂度 二,具体实现 1.直接选择排序 基本思想:在长度为n的序列中,第一次遍历找到该序列的最小值,替换掉第一个元素,接着从第二个元素开始遍历,找到剩余序列中的最小值,替换掉第二个元 ...