学习总结15
# 封印
## 题目背景
很久以前,魔界大旱,水井全部干涸,温度也越来越高。为了拯救居民,夜叉族国王龙溟希望能打破神魔之井,进入人界“窃取”水灵珠,以修复大地水脉。可是六界之间皆有封印,神魔之井的封印由蜀山控制,并施有封印。龙溟作为魔界王族,习有穿行之术,可任意穿行至任何留有空隙的位置。然而封印不留有任何空隙! 龙溟无奈之下只能强行破除封印。破除封印必然消耗一定的元气。为了寻找水灵珠,龙溟必须减少体力消耗。他可以在破除封印的同时使用越行术。
## 题目描述
神魔之井的封印共有 n 层,每层封印都有一个坚固值。身为魔族的龙溟单独打破一层封印时需要消耗的元气为该层封印的坚固值和封印总层数 n 的平方的乘积; 但他也可以打破第 i 层到第 j 层之间的所有封印( i<j),总元气消耗为第 i,j 层封印的坚固值之和与第 i,j 层之间所有封印层(包括第 i,j 层)的坚固值之和的乘积,但为了不惊动蜀山,第 i,j 层封印的坚固值之和不能大于 t (单独打破可以不遵守)。
## 输入格式
第一行包含两个正整数 n 和 t。
第二行有 n 个正整数,第 i 个数为 ai,表示第 i 层封印的坚固值。
## 输出格式
仅一行,包含一个正整数,表示最小消耗元气。
## 样例 #1
### 样例输入 #1
```
6 10
8 5 7 9 3 5
```
### 样例输出 #1
```
578
```
## 提示
#### 样例解释
先单独打破第一层,再用越行术从第二层直接打破到最后一层。 这样消耗元气 8 * 6^2 + (5 + 5) * (5 + 7 + 9 + 3 + 5) = 578。
#### 数据范围
对于 10% 的数据, n<=10;
对于 50% 的数据, n<=100;
对于 70% 的数据, n<=500;
对于 100% 的数据, n<=1000, ai(1 <= i <= n) , t <= 20000。
解题思路
利用前缀和的方法来纪录前几项的和,用一个dp数组来保存计算过的数值保存打破第n层所用的最小元气。
代码
#include <bits/stdc++.h>
using namespace std;
long long g[1010],j[1010],dp[1010];
int main()
{
long long n,t,x,y;
scanf("%lld%lld",&n,&t);
for(x=1;x<=n;x++)
scanf("%lld",&g[x]);
for(x=1;x<=n;x++)
j[x]=g[x]+j[x-1];
for(x=1;x<=n;x++)
{
dp[x]=g[x]*(n*n)+dp[x-1];
for(y=1;y<x;y++)
{
if(g[x]+g[y]<=t)
{
dp[x]=min(dp[x],(g[x]+g[y])*(j[x]-j[y-1])+dp[y-1]);
}
}
}
printf("%lld",dp[n]);
return 0;
}
# 奇怪的函数
## 题目描述
使得 x^x 达到或超过 n 位数字的最小正整数 x 是多少?
## 输入格式
一个正整数 n。
## 输出格式
使得 x^x 达到 n 位数字的最小正整数 x。
## 样例 #1
### 样例输入 #1
```
11
```
### 样例输出 #1
```
10
```
## 提示
对于全部数据,1<= n<= 2* 10^9。
解题思路
用二分法来查找使得 x^x 达到 n 位数字的最小正整数 x,利用log10()函数来计算位数。
代码
#include <bits/stdc++.h>
using namespace std;
int main()
{
int m,n,l=1,r=300000000;
scanf("%d",&n);
n--;
while(l<r)
{
m=(l+r)/2;
if(m*log10(m)<n)l=m+1;
else
r=m;
}
printf("%d",l);
return 0;
}
今日总结
今天复习了一下二分、双指针的应用,对二分查找的认识更深了。