10-24机房测试

91 篇文章 1 订阅
49 篇文章 0 订阅

出现的问题:
T1我贪错心了。。。。。。
T2是从1-k任何一个房间走都可以走到1,k+1-n任何一个走不能走到1.
我理解反了,理解成了存在性问题,写出来的爆暴力样例都过不了。。。
T3人家巨人只能往前跳,我认为可以往后跳。于是我认为这题太麻烦了,做个屁啊。
然后今天就GG了
很绝望啊。

T1 小G搭积木

题目描述
小 G 喜欢搭积木。小 G 一共有 n 块积木,并且积木只能竖着一块一块的摞,可
以摞多列。小 G 的积木都是智能积木,第 i 块积木有一个情绪值 X i 。当摞在该积
木上面积木总数超过 X i 时,i 号积木就会不高兴。小 G 情商这么高,肯定不希望
有积木不高兴。但是他又希望每块积木都被用上,并且摞的积木列的总数最少。你
能帮帮萌萌的小 G 吗?

输入格式
输入文件第一行一个数字 n,含义如题目所述。
第 2 行一共 n 个数,第 i 个数为 X i ,含义如题目所述。

输出格式
输出一个数字,表示最小的积木列数目
样例输入 1
3
0 0 10
样例输出 1
2
样例输入 2
4
0 0 0 0
样例输出 2
4
数据范围
30% 数据,1 ≤ n ≤ 10
60% 数据,1 ≤ n ≤ 100
80% 数据,1 ≤ n ≤ 1000
100% 数据,1 ≤ n ≤ 5000
对于所有数据点,都有 X i ≤ n


正解贪心:
把往上添方块变为往下垫方块。
把方块从小到大添上去。
一定要找一摞方块数跟当前添的方块最接近的,这样才发挥了最大作用。

#include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxm=9999;
int q[maxm];
int h[maxm],tot; 
bool comp(int a,int b)
{
    return a>b;
}
int main()
{
    freopen("box.in ","r",stdin);
    freopen("box.out","w",stdout);
    int n;
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
     scanf("%d",&q[i]);
    sort(q+1,q+n+1);
    int tot=1;
    h[1]=1;
    for(int i=2;i<=n;i++)
    {
        int id=0;
        for(int j=1;j<=tot;j++)
         if(h[j]<=q[i])
          {
            if(id==0) id=j;
            else
             if(h[id]<h[j]) id=j;
          }
        if(id==0) h[++tot]=1;
        else h[id]++;
    } 
    printf("%d",tot);
} 

T2 小 G 的城堡

题目描述
小 G 家有一座城堡。城堡里面有 n 个房间,每个房间上都写着一个数字 p i 。小
G 拉着几个小伙伴在城堡里面玩耍,他们约定,如果某个人当前站在 i 房间里面,下
一步这个人就会去 p i 房间,再下一步这个人去 p p i 。
为了增加趣味性,小 G 想重新书写每个房间的 p i ,以满足:
• 如果从编号 1 到 k 中的某个房间开始,按照规则走,必须能够走到 1 号房间。
特别地,如果从 1 号房间开始走,也要能够走回 1 号房间(至少走一步,如果
p 1 = 1,从 1 走到 1 也算合法)。
• 如果从编号大于 k 的某个房间开始,按照规则走,一定不能走到 1 号房间。
小 G 想知道,有多少种书写 p i 的方案,可以满足要求。

输入格式
输入文件一行两个数字 n,k,含义如题。

输出格式
输出文件一个数字,表示合法的方案数。答案对 10 9 + 7 取模。
样例输入 1
5 2
样例输出 1
54
样例输入 2
7 4
样例输出 2
1728
数据范围
对于 40% 的数据,1 ≤ n ≤ 8
对于 70% 的数据,1 ≤ n ≤ 10 5
对于 100% 的数据,1 ≤ n ≤ 10 18 ,1 ≤ k ≤ min(8,n)。


对于1-k联通的方案数,我们可以用暴力求出来。
k最大为8,打表即可。
后面的只能和后面的连,方案数即为(n-k)^(n-k)。
后来发现前面的方案数为(k-1)^k
乘法原来搞一搞,快速幂即可。

#include <cstdio>
#include <iostream>
#define ll long long 
using namespace std;
const int mod=1e9+7;
ll n,k,ans;
ll fast_pow(ll x,ll y) 
{
    ll ans=1;
    while(y)
    {
        if(y%2) ans=(ans*x)%mod;
        y/=2ll;
        x=(x*x)%mod;
    }
    return ans%mod;
}
int main()
{
    scanf("%lld%lld",&n,&k);
    printf("%lld",fast_pow(k,k-1)*fast_pow(n-k,n-k)%mod);
}

T3 跳跃

题目描述
美丽国有 n 座小岛。这些小岛排成了一条直线,依次编号为 0,1,2,3… 有的小岛
上有金块,有的小岛上没有。美丽国有一个巨人 Bob,有一天他决定从第 0 个岛开
始,一直往后跳,看看自己能收集多少金块。
当然,Bob 不是没有目的性的乱跳;相反,Bob 的跳跃要满足以下规则:
• 首先 Bob 从 0 跳到 d 岛屿
• 假如 Bob 上一次跳了 l 步,则 Bob 下一次可以选择跳 l、l − 1、l + 1 步。注
意:所跳的步数不能小于 1,即如果上一次跳跃的步数为 1,下一次跳跃的步
数只能是 1 或者 2。
在这样的规则下,Bob 想知道,他最多能拿到多少金块?

输入格式
输入第一行两个整数 n,d,分别表示有金块的岛屿的个数,和 Bob 第一步要
跳的步数。
接下来 n 行,每行一个整数 id,表示编号为 id 的岛屿上有金块。

输出格式
输出仅一行,表示 Bob 最多能收集多少金块。
样例输入 1
4 10
10
21
27
27
样例输出 1
3
样例输入 2
8 8
9
19
28
36
45
55
66
78
样例输出 2
6
数据范围
对于 30% 的数据,1 ≤ n,d,id ≤ 100
对于 70% 的数据,1 ≤ n,d,id ≤ 1000
对于 100% 的数据,1 ≤ n,d,id ≤ 30000


DP[i][j]为i位置下次跳j步能捡到的最多的金子数目。
转移
DP[i][j]=max(DP[i+j][j-1],DP[i+j][j+1],dp[i+j][j])+a[i]。

j多大?30000?
空间不够。
考虑一下最多最少跳几步。
最坏的情况,从1开始走。
每次+1
那么最多跳的步数即为 初始+n(n+1)/2
最小的同理。

#include <cstdio>
#include <iostream>
using namespace std;
int flag[30021];
int dp[30021][3001];
int main()
{
    int n,d;
    int max_d=0;
    scanf("%d%d",&n,&d);
    for(int i=1,x;i<=n;i++)
     scanf("%d",&x),flag[x]++,max_d=max(max_d,x);
    for(int i=max_d;i>=d;i--)
     for(int j=0;j<=700;j++)
      {
        int x=j-350;
        if(d+x<0) continue;
        dp[i][j]=flag[i];
        if(i+d+x<=max_d) 
         dp[i][j]+=max(max(dp[i+d+x][j-1],dp[i+d+x][j]),dp[i+d+x][j+1]);
      }
    printf("%d",max(dp[d][350],max(dp[d][349],dp[d][351])));
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值