Day1

事实上D1的题目还是比较简单的= =然而D1T2爆炸了就十分尴尬……错失一波键盘

看题

T1

传送门

Description

现在你手里有一个计算器,上面显示了一个数\(S\),这个计算器十分的牛逼,他只有两个按钮,分别可以把屏幕上显示的数加上\(1\)或者减去\(1\)。并且,如果计算器屏幕上的数变成了负数,那么计算器就会损坏。现在你想要在\(K\)次操作之内吧屏幕上的数字变成\(T\),而且不让计算器损坏,求一共有多少种方案。

两种方案不同当且仅当按钮被按下的序列不同

Input

一行三个整数\(S,T,K\)

Output

一行一个正整数,表示答案

Sample Input

0 1 3

Sample Output

3

Hint

\(For~All:\)

\(0~\leq~S,T,K~\leq~100000\)

\(For~30~percents:\)

\(S,T,K~\leq~10\)

\(For~60~percents:\)

\(S,T,K~\leq~1000\)

Solution

前30分枚举加和减

60分做法:DP。

设\(f_{i,j}\)为,第\(i\)次操作将计算器变成\(j\)的方案数。转移显然,枚举第\(i\)次加一还是减一。

\[f_{i,j}=f_{i-1,j-1}+f_{i-1}{j+1}$$。当$j=0$时不能从$j-1$转移。答案显然就是$\sum_{i=0}^{k}~f_{k,T}$,边界为$f_{0,S}=1$

满分做法:数学推导。

由于$S$到$T$的方案数严格等价于$T$到$S$的方案数,故不妨设$S~\leq~T$

考虑题目事实上等价于在一个平面直角坐标系中,有一个点$(S,0)$,求这个点到$(T,k)$的方案数。其中$0~\leq~k~\leq~K$

每次移动只能从$(x,y)$移动到$(x+1,y+1)$或$(x-1)(y+1)$。其中不允许越过$x=0$这条线。考虑这么做的方案数,等价于将坐标轴旋转$45°$,以原先的$(S,0)$为原点,不允许越过$y=x+S$这条直线,到达$(T-S,k)$的方案数。先考虑不存在不许越过直线的限制,那么方案数即为$C_{T-S+k}^{k}$。考虑不合法的方案。发现将不合法的方案在直线下方的部分关于直线对称后与他关于直线的对称点到目标的方案一一对应。于是显然另一个方案数可以求出。做差即为答案。

### Code

~~我懒得写了所以就把std放上来了~~

~~这std写的真丑~~

```cpp
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;

const int N = (int)2e5, mod = (int)1e9 + 7;
typedef long long ll;

int S, T, K;
int fac[N + 10], ifac[N + 10];

int pow(int x, int y) {
ll t = x, r = 1;
for ( ; y; y >>= 1, t = t * t % mod)
if (y & 1) r = r * t % mod;
return r;
}

void preprocessing() {
fac[0] = 1;
for (int i = 1; i <= N; ++i) fac[i] = (ll)fac[i - 1] * (ll)i % mod;
ifac[N] = pow(fac[N], mod - 2);
for (int i = N - 1; i >= 0; --i) ifac[i] = (ll)ifac[i + 1] * (ll)(i + 1) % mod;
}

int c(int n, int r) {
return (ll)fac[n] * (ll)ifac[r] % mod * (ll)ifac[n - r] % mod;
}

int main() {

preprocessing();
scanf("%d %d %d", &S, &T, &K);
if (S > T) swap(S, T);

int ans = 0;
for (int i = 0; i <= K; ++i) {
if ((i + T - S) & 1) continue;
int x = (i - T + S) >> 1, y = (i + T - S) >> 1;
if (x < 0) continue;
(ans += c(x + y, x)) %= mod;
if (x > S) (ans += (mod - c(x + y, x - S - 1))) %= mod;
}

printf("%d\n", ans);
return 0;
}
```

## T2

[传送门](https://www.luogu.org/problemnew/show/T50010)

### Description

有一个工厂一共有$n$个排成一排的机器,其中第$i$台机器的效率是$e_i$。

机器有开或关两种状态,显然当所有机器都开着时工作效率可以达到最大。但是由于工厂的供电系统出现了故障,不能够同时开启任意连续$k$台机器,否则工厂就会爆炸。

求工厂在不发生爆炸的前提下能达到的最大效率

### input

第一行两个整数$n$和$k$

接下来$n$行,每行一个整数代表$e_i$

### Output

一行一个数代表答案

### Sample Input

```
5 2
1
2
3
4
5
```

### Sample Output

```
12
```

### Hint

$For~All:$

$1~\leq~n,k~\leq~10^5~,~1~\leq~e_i~\leq~10^9$

$For~30~percents:$

$1~\leq~n~\leq~100$

### Solution

DP。

考虑设$f_i$为前$i$个的答案,其中一定不选第$i$个。显然可以通过枚举哪一个不选进行转移。$f_i=$$\max\{f_j+e_{j+1}+e_{j+2}+...+e_{i}\}$,其中满足$i-k~<~j~<~i$。$e_i$显然可以前缀和处理。另外发现因为$k$恒定,所以转移的左端点时单调不降的。于是可以单调队列把整个复杂度降低到$O(n)$。事实上使用线段树维护区间最大值也是可以的。

## Code

```cpp
#include<cstdio>
#define rg register
#define ci const int
#define cl const long long int

namespace IO {
char buf[110];
}

typedef long long int ll;

template <typename T>
inline void qr(T &x) {
char ch=getchar(),lst=' ';
while((ch > '9') || (ch < '0')) lst=ch,ch=getchar();
while((ch >= '0') && (ch <= '9')) x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
if(lst == '-') x=-x;
}

template <typename T>
inline void write(T x,const char aft,const bool pt) {
if(x < 0) {putchar('-');x=-x;}
rg int top=0;
do {
IO::buf[++top]=x%10+'0';x/=10;
} while(x);
while(top) putchar(IO::buf[top--]);
if(pt) putchar(aft);
}

template <typename T>
inline T mmax(const T a,const T b) {return a > b ? a : b;}
template <typename T>
inline T mmin(const T a,const T b) {return a < b ? a : b;}
template <typename T>
inline T mabs(const T x) {return x < 0 ? -x : x;}

template <typename T>
inline void mswap(T &a,T &b) {
T temp=a;a=b;b=temp;
}

const int maxn = 100010;

int n,k,front,end;
ll frog[maxn],que[maxn],sum[maxn];

int main() {
qr(n);qr(k);
for(rg int i=1;i<=n;++i) {qr(sum[i]);sum[i]+=sum[i-1];}
front=end=1;
for(rg int i=1;i<=n;++i) {
if(i-que[front] > k) ++front;
while((front <= end) && ((frog[que[end]]-sum[que[end]]) <= (frog[i]-sum[i]))) --end;
que[++end]=i;
frog[i+1]=frog[que[front]]-sum[que[front]]+sum[i];
}
write(frog[n+1],'\n',true);
return 0;
}
```

## T3

[传送门](https://www.luogu.org/problemnew/show/T50011)

### Description

![qwq](https://cdn.luogu.org/upload/pic/35123.png )

### Input

![qwq](https://cdn.luogu.org/upload/pic/35124.png)

### Output

对于每组询问输出一行代表答案

### Sample Input

```
6
M 1 6
C 1
M 2 4
M 2 6
C 3
C 4
```

### Sample Output

```
1
0
2
```

### Solution

这不是没穿衣服的带权并查集嘛

### Code

```cpp
// i forgot to reset the seed of the rand
// maybe i will get zero pts
// upd: i ain't get WA for this task
// i feel very happy
#include<cstdio>
#define rg register
#define ci const int
#define cl const long long int

namespace IO {
char buf[110];
}

template <typename T>
inline void qr(T &x) {
char ch=getchar(),lst=' ';
while((ch > '9') || (ch < '0')) lst=ch,ch=getchar();
while((ch >= '0') && (ch <= '9')) x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
if(lst == '-') x=-x;
}

template <typename T>
inline void write(T x,const char aft,const bool pt) {
if(x < 0) {putchar('-');x=-x;}
rg int top=0;
do {
IO::buf[++top]=x%10+'0';x/=10;
} while(x);
while(top) putchar(IO::buf[top--]);
if(pt) putchar(aft);
}

template <typename T>
inline T mmax(const T a,const T b) {return a > b ? a : b;}
template <typename T>
inline T mmin(const T a,const T b) {return a < b ? a : b;}
template <typename T>
inline T mabs(const T x) {return x < 0 ? -x : x;}

template <typename T>
inline void mswap(T &a,T &b) {
T temp=a;a=b;b=temp;
}

const int maxn = 30010;

int up[maxn],down[maxn],dist[maxn];

int findup(ci);
int finddown(ci);

int main() {
freopen("cubes.in","r",stdin);
freopen("cubes.out","w",stdout);
rg int m=0;qr(m);
for(rg int i=1;i<=maxn;++i) up[i]=i,down[i]=i,dist[i]=0;
rg int a,b;rg char ch;
while(m--) {
ch=getchar();
while((ch != 'M') && (ch != 'C')) ch=getchar();
if(ch == 'M') {
a=b=0;qr(a);qr(b);
a=finddown(a);b=findup(b);
down[a]=b;up[b]=a;dist[a]=1;
}
else {
a=0;qr(a);
finddown(a);
write(dist[a],'\n',true);
}
}
return 0;
}

int findup(ci x) { return up[x] != x ? up[x]=findup(up[x]) : x; }

int finddown(ci x) {
if(down[x] == x) return x;
int tk=finddown(down[x]);
dist[x]+=dist[down[x]];
return down[x]=tk;
}
```

## Summary

这套题大概是6天里面最简单的一套了……起码有260保底……然而竟然挂在了最拿手的DP上……

在写DP的时候发现有一部分转移无法优化时,可以考虑这一块转移是否是必须的,如果不是,可以直接删除该转移

一定记得srand!\]

【套题】qbxt国庆刷题班D1的更多相关文章

  1. 【套题】qbxt国庆刷题班D2

    D2 今天的题感觉还是好妙的 T1 传送门 Description 现在有一张\(n\)个节点\(m\)条边的无向连通图\(G=(V,E)\),满足这张图中不存在长度大于等于3的环且图中没有重边和自环 ...

  2. JS、JAVA刷题和C刷题的一个很重要的区别

    就是最近在做树方面的题时,发现JS和JAVA刷题和C刷题的一个很重要的区别就是传入null的区别 当遍历的时候,C传参数时可以传进去null的指针,因为递归进去,出来时,指针还是指着那个地方 但是JS ...

  3. 再也不用c刷题了!!——c++刷题必备

    致读者: 博主是一名数据科学与大数据专业大二的学生,真正的一个互联网萌新,写博客一方面是为了记录自己的学习历程,一方面是希望能够帮助到很多和自己一样处于困惑的读者.由于水平有限,博客中难免会有一些错误 ...

  4. 2017北京国庆刷题Day5 afternoon

    期望得分:100+60+100=260 实际得分:0+60+40=100 设图中有m个环,每个环有si条边,有k条边不在环中 ans= (2^s1 -2)*( 2^s2 -2)* (2^s3 -2)… ...

  5. 2017北京国庆刷题Day1 afternoon

    期望得分:100+100+100=300 实际得分:100+100+100=300 T1 一道图论好题(graph) Time Limit:1000ms   Memory Limit:128MB 题目 ...

  6. 2017北京国庆刷题Day7 morning

    期望得分:100+0+100=200 实际得分:100+20+0=120 离散化搞搞 #include<cstdio> #include<iostream> #include& ...

  7. 2017北京国庆刷题Day3 morning

    期望得分:100+60+0=160 实际得分:100+30+0=130 考场上用的哈希 #include<cstdio> #include<cstring> #include& ...

  8. 2017北京国庆刷题Day2 afternoon

    期望得分:100+100+50=250 实际得分:100+70+50=220 T1 最大值(max) Time Limit:1000ms   Memory Limit:128MB 题目描述 LYK有一 ...

  9. 2017北京国庆刷题Day2 morning

    期望得分:100+100+40=240 实际得分:100+40+0=140 T1 一道图论神题(god) Time Limit:1000ms   Memory Limit:128MB 题目描述 LYK ...

随机推荐

  1. HTMLTestRunner.py(Python3)

    """A TestRunner for use with the Python unit testing framework. Itgenerates a HTML re ...

  2. C 计算员工工资

    #include <stdio.h> int main(int argc, char **argv) { //定义四个变量 g每小时固定的工资 40 固定工作时间 pay工资 hours员 ...

  3. leetcode-生成括号(回溯算法)

     转载出处:https://blog.csdn.net/yanerhao/article/details/68561290 生成括号     给出 n 代表生成括号的对数,请你写出一个函数,使其能够生 ...

  4. [SHELL]shell中的数学运算

    一,expr  太麻烦,看的脑壳疼 二,使用方括号 !!!! bash shell用这种方法只支持整数运算,z shell倒是支持浮点型运算 var_1= var_2= var_3= my_var_1 ...

  5. git branch 分支与合并

    在使用 git 进行分支开发与合并的时候需要用到这些命令.其他基本 git 命令参考 Git 简易食用指南 git branch 查看分支 git branch 查看当前分支情况 创建分支 git b ...

  6. scipy 图像处理-深度学习

    scipy 图像处理(scipy.misc.scipy.ndimage).matplotlib 图像处理 from scipy.misc import imread / imsave / imshow ...

  7. LeetCode 135——分发糖果

    1. 题目 2. 解答 初始化左序奖赏全为 1,从左往右遍历,如果右边的人评分比左边高,右边奖赏比左边奖赏增 1. 初始化右序奖赏全为 1,从右往左遍历,如果左边的人评分比右边高,左边奖赏比右边奖赏增 ...

  8. 将SqlDataReader 数据集转化为datatbale ,在将datatable 转化为iList

    public IList GetModelList(string tablename, string where) { IList list = null; DataTable dataTable = ...

  9. Python3 异常与断言

    1.异常 当出现错误时,程序就会发生异常 num1=input('Please input a num1: ') num2=input('Please input a num2: ') print(f ...

  10. JavaScript控制href属性进行钓鱼

    前一阵子,发现JavaScript中允许临时改变<a>标签的href属性,当改变其属性后你点击它可能看不出有多严重,但是,它可以通过欺骗手段来诱骗用户透露他们的详细资料. // Uncom ...