# 第一届梦羽杯题目（后六题）浅析

## G 爱女装的社长

### 题目大意：

n个位置排成一列，每个位置可以填1,2,3，要求不能有连续三个位置填相同的数，求方案数
$$n<=10^5$$

### 算法思路

$f_{i,1}=f_{i-1,1}*2+f_{i-1,2}*2$

$f_{i,2}=f_{i-1,1}$

### 代码

/*********************************************************************
WRITER:YZHX
DATE:2023.9.12
*********************************************************************/
#include <bits/stdc++.h>
using namespace std;
#define re register
#define in inline
#define ll long long
#define get getchar()
#define db double
int t = 0, x = 1;
char ch = get;
while ((ch < '0' || ch > '9') && ch != '-')
ch = get;
if (ch == '-')
ch = get, x = -1;
while (ch <= '9' && ch >= '0')
t = t * 10 + ch - '0', ch = get;
return t * x;
}
const int mod = 1e9 + 7;
ll f[100100][3];
in void pre() {
int n = 100000;
f[1][1] = 3;
for (re int i = 2; i <= n; ++i)
{
f[i][1] = (f[i - 1][1] * 2 % mod + f[i - 1][2] * 2 % mod) % mod;
f[i][2] = f[i - 1][1];
}
}
int main() {
// freopen(".in","r",stdin);
// freopen(".out","w",stdout);
pre();
while (T--) {
cout << (f[n][1] + f[n][2]) % mod << endl;
}
return 0;
}



## H女装社长的威胁

### 题目大意

$$n<=10^5, k<=10^{12}, a_i<=10^9$$

### 算法解析

/*********************************************************************
WRITER:YZHX
DATE:2023.9.12
*********************************************************************/
#include <bits/stdc++.h>
using namespace std;
#define re register
#define in inline
#define ll long long
#define get getchar()
#define db double
int t = 0, x = 1;
char ch = get;
while ((ch < '0' || ch > '9') && ch != '-')
ch = get;
if (ch == '-')
ch = get, x = -1;
while (ch <= '9' && ch >= '0')
t = t * 10 + ch - '0', ch = get;
return t * x;
}
const int _ = 1e5 + 23;
ll n, k, a[_], b[_];
in int check(int mid) {
int l, r, t;
for (re int i = 1; i <= n - mid + 1; ++i) {
l = i, r = i + mid - 1, t = (l + r) >> 1;
ll w = a[t] * (t - l + 1) - (b[t] - b[l - 1]) + (b[r] - b[t]) - a[t] * (r - t);
if (w < k)
return 1;
}
return 0;
}
int main() {
// freopen(".in","r",stdin);
// freopen(".out","w",stdout);
for (re int i = 1; i <= n; ++i)
sort(a + 1, a + n + 1);
for (re int i = 1; i <= n; ++i)
b[i] = b[i - 1] + a[i];
ll sum = 0, l = 1, r = n, ans = 0;
while (l <= r) {
int mid = (l + r) >> 1;
if (check(mid))
l = mid + 1, ans = mid;
else
r = mid - 1;
}
printf("%lld\n", ans);
return 0;
}



## J模拟跑酷

### 题目描述

1、普通跑道，用'.'表示，通过一个单位的普通跑道需要1s
2、上坡，用‘&’表示，通过一个单位的上坡跑道需要2s
3、下坡，用‘%’表示，通过一个单位的下坡跑道需要0.5s
4、障碍跑道,用‘\$’表示，通过障碍跑道需要5s

n不大于5

### 解题思路

（因为yzhx太饿了，代码被吃了奥）

## K拔萝卜

### 题目描述

$$1<=c<=n<=100$$ $$x_i,a_i<=10^9$$

### 解题思路

n<100???这种数据通常是很暧昧的，既不会要求太高的数据结构和算法板子，也不会是暴力能过的，所以，继续考虑动态规划(DP)。
DP题最关键几点就是：
1.怎样记录状态
2.怎样通过已知状态合理转移 (考虑复杂度) 到未知状态
3.如何通过记录的状态获取答案

$$f_{l,r,0/1}$$表示当前已关闭的机器区间是[l,r],我们自身的位置是l或者r（用0/1表示）。

dp[i][j][1]=min( dp[i][j-1][0]+(dis[j]-dis[i])*(sum[n]+sum[i-1]-sum[j-1]),dp[i][j-1][1]+(dis[j]-dis[j-1])*(sum[n]+sum[i-1]-sum[j-1]) );
dp[i][j][0]=min( dp[i+1][j][0]+(dis[i+1]-dis[i])*(sum[n]+sum[i]-sum[j]),dp[i+1][j][1]+(dis[j]-dis[i])*((sum[n]+sum[i]-sum[j]) ) ) ;


### 代码

/*********************************************************************
WRITER:YZHX
DATE:2023.9.12
*********************************************************************/
#include<bits/stdc++.h>
using namespace std;
#define re register
#define ll long long
#define in inline
#define get getchar()
{
int t=0; char ch=get;
while(ch<'0' || ch>'9') ch=get;
while(ch<='9' && ch>='0') t=t*10+ch-'0', ch=get;
return t;
}
int n,c;
const int _=101;
ll sum[_],dp[_][_][2],dis[_],v[_];
int main()
{
for(re int i=1;i<=n;i++)
memset(dp,0x3f,sizeof(dp));
dp[c][c][1]=0,dp[c][c][0]=0;
for(re int j=c;j<=n;j++)
for(re int i=j-1;i;i--)
{
dp[i][j][1]=min( dp[i][j-1][0]+(dis[j]-dis[i])*
(sum[n]+sum[i-1]-sum[j-1]),
dp[i][j-1][1]+(dis[j]-dis[j-1])*(sum[n]+sum[i-1]-sum[j-1]) );
dp[i][j][0]=min( dp[i+1][j][0]+(dis[i+1]-dis[i])*
(sum[n]+sum[i]-sum[j]),
dp[i+1][j][1]+(dis[j]-dis[i])*((sum[n]+sum[i]-sum[j]) ) ) ;
}
cout<<min(dp[1][n][0],dp[1][n][1]);
}


## L养一群龙吧

### 题解

（没写不想动）

posted @ 2023-10-01 01:27  yzhx  阅读(14)  评论(0编辑  收藏  举报