长安大学第四届“迎新杯”程序设计竞赛 F 打铁的箱子数学/进制思维/折半枚举

Posted Roni

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了长安大学第四届“迎新杯”程序设计竞赛 F 打铁的箱子数学/进制思维/折半枚举相关的知识,希望对你有一定的参考价值。

题目描述

作为彩虹岛上最擅长打铁的人,??????今天一共打了??块大小为1的铁。为了保存这些铁块,他打算制作若干个箱子。其中,第1个箱子的容量为1(可装1块铁),之后每个箱子的容量都是它前一个箱子的容量的2倍。
但是他只会打铁,并不擅长制作箱子。制作完成后,他发现第1个箱子的容量是2(而不是1),之后每个箱子的容量都比它前一个箱子的容量的2倍少1,即第2个箱子的容量是3 = 2 × 2 − 1,第3个箱子的容量是5 = 3 × 2 − 1,第4个箱子的容量是9 = 5 × 2 − 1,依此类推。
作为一个勤俭节约的人,??????想知道能否把这??块铁全部放入箱子中并使得所有装有铁块的箱子都装满了且没有空余。

输入描述:

输入第一行为一个整数??(1 ≤ ?? ≤ 100),表示一共有??组数据。
对于每组测试数据:
第一行为一个整数??(1 ≤ ?? ≤ 109),表示??????一共打了??块铁。

输出描述:

对于每组测试数据,如果能够按照要求放进箱子里面则输出“YES”,否则输出“NO”。
示例1

输入

2
1
8

输出

NO
YES

说明

对于第一组样例,无法按照要求放入箱子中。
对于第二组样例,用容量为3和容量为5的箱子恰好能够放下8块铁。


 【分析】:每个背包的大小是个方程式f(n)=2^(n-1)+1 ,所以每个生成数是一个数加上其二进制上1的数目 。我们枚举1的数目i,最多不超过25,减去其并计算减去后的数的二进制1的数目n,如果n等于i就成功了。有2^(n-1)这个东西,它组成的数系能覆盖整个整数系, 但加了个1 。可知二进制中有几个1就加几个1。
【代码】:
技术分享图片
#include <bits/stdc++.h>
using namespace std;
int main(){
    int T,min;cin>>T;
    while(T--)
    {
        int x,i;
        cin>>x;
        if(x>31) min=31;
        else min=x;
        for(i=1;i<=min;i++)
            if(__builtin_popcount(x-i)==i) {cout<<"YES";break;}
        if(i>min) cout<<"NO";
        cout<<\n;
    }
 
    return 0;
}
二进制

 

技术分享图片
#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
#define INFLL 0x3f3f3f3f3f3f3f3f
#define x first
#define y second
#define LL long long
using namespace std;
const int maxn = 2e5+5;
int T;
int n;
LL a[35];
LL num1[2<<16];
LL num2[2<<16];
int p1 = 0;
int p2 = 0;
void dfs1(int l,int r,LL sum,int deep)
{
    if(deep==r+1){
        num1[p1++] = sum;
        return ;
    }
    dfs1(l,r,sum,deep+1);
    dfs1(l,r,sum+a[deep],deep+1);
}
void dfs2(int l,int r,LL sum,int deep)
{
    if(deep==r+1){
        num2[p2++] = sum;
        return ;
    }
    dfs2(l,r,sum,deep+1);
    dfs2(l,r,sum+a[deep],deep+1);
}

void init()
{
    a[0] = 2;
    for(int i = 1;i<31;i++){
        a[i] = a[i-1]*2-1;
    }
    dfs1(0,31/2,0,0);
    dfs2(31/2+1,30,0,31/2+1);
    sort(num1,num1+p1);
    sort(num2,num2+p2);
}
int main()
{
    init();
   scanf("%d",&T);
   while(T--){
        scanf("%d",&n);
        int falg = 0;
        for(int i = 0;i<p1;i++){

            if(num1[i]>n) break;
            int p = lower_bound(num2,num2+p2,n-num1[i])-num2;
           // cout<<num1[i]<<‘ ‘<<p<<‘ ‘<<num2[p]<<endl;
            if(p<p2&&num2[p]+num1[i]==n){
                falg = 1;
                break;
            }
        }
        if(falg){
            puts("YES");
        }
        else{
            puts("NO");
        }
   }
}
折半枚举

 

以上是关于长安大学第四届“迎新杯”程序设计竞赛 F 打铁的箱子数学/进制思维/折半枚举的主要内容,如果未能解决你的问题,请参考以下文章

长春理工大学第十四届程序设计竞赛(重现赛)F

长春理工大学第十四届程序设计竞赛F Successione di Fixoracci——找规律&&水题

湖南中医药大学信息科学与工程学院第四届大学生程序设计竞赛——正式赛题解

湖南中医药大学信息科学与工程学院第四届大学生程序设计竞赛——正式赛题解

湖南中医药大学信息科学与工程学院第四届大学生程序设计竞赛——正式赛题解

高分!!电子竞赛