\(Codeforces-Round 767\) (Div. 2) F2. \(Game \ on \ Sum\)

\(HERE\)

题意

\(QZS\) 和 \(HANGRY\) 玩游戏。

游戏共有 \(n\) 轮, 对于整一局游戏给定一个 \(K\) , 游戏的过程是在改变一个数 \(a\) 的值 , 初始为 \(1\) .

在每一轮中 \(QZS\) 会在 \([1 , k]\) 的区间里取出一个 \(\bf{实数}\) , \(HANGRY\) 选择用 \(a\) 加上这个实数还是减去这个实数 , \(HANGRY\) 的目的是让 \(a\) 最小 , \(QZS\) 相反.

在这 \(n\) 轮中 , \(HANGRY\) 至少选择 \(m\) 轮选择加 .

\(HANGRY\) 和 \(QZS\) 都是绝顶聪明的 , 这意味着他们会选择最优解 .

问最后的 \(a\) 是多少 . 多测.答案对 \(1e9+7\) 取模.

数据范围:

$n \le 10^6 , m \le n , T \le 5 \times 10^5 \sum n = 10^6 $

\(\sum n\) 为每个测试点所有测试数据中 \(n\) 的和.

题解

\(O(nm)\) (<100 pts)

考虑 \(DP\)

\(dp_{i,j}\) 表示长度为 \(i\) , 选了 \(j\) 个减。

则方程为:

\[dp_{i , j} = \frac{dp_{i - 1 , j} + dp_{i - 1 , j - 1}}{2}
\]

显然

code

114514
#include <bits/stdc++.h>
#define int long long
using namespace std ;
const int N = 2e3 + 10 ;
const int mod = 1e9 + 7 ; int dp[N][N] , n , T , m , K ;
int nueyong ; inline int read() {
int x = 0 , f = 1 ;
char c = getchar() ; while ( c < '0' || c > '9' ) { if ( c == '-' ) f = -f ; c = getchar() ;
} while ( c >= '0' && c <= '9' ) {
x = x * 10 + c - '0' ;
c = getchar() ;
} return x * f ;
} inline int Regular_Quick_Pow( int a , int b ) {
int ans = 1 ; while ( b > 0 ) { if ( b & 1 ) ans = ( ans * a ) % mod ; b >>= 1 ; a = ( a * a ) % mod ;
} return ans ;
} signed main() { #ifndef ONLINE_JUDGE
freopen( "1.in" , "r" , stdin ) ;
freopen( "1.out" , "w" , stdout ) ;
#endif T = read() ; nueyong = Regular_Quick_Pow( 2 , mod - 2 ) ; while ( T -- ) { n = read() , m = read() , K = read() ;
dp[1][0] = K , dp[1][1] = 0 ; for ( int i = 2 ; i <= n ; ++ i ) { dp[i][0] = ( i * K ) % mod ; for( int j = 1 ; j <= min(i - 1 , n - m) ; ++ j ) { dp[i][j] = ( ( ( dp[i - 1][j - 1] + dp[i - 1][j] ) % mod ) * nueyong ) % mod ; } } cout << dp[n][n - m] << '\n' ;
}
}

组合方法

我们目前把这个东西写出来

    1     0     0     0     0     0     0     0     0     0     0
4 1 0 0 0 0 0 0 0 0 0
12 5 1 0 0 0 0 0 0 0 0
32 17 6 1 0 0 0 0 0 0 0
80 49 23 7 1 0 0 0 0 0 0
192 129 72 30 8 1 0 0 0 0 0
448 321 201 102 38 9 1 0 0 0 0
1024 769 522 303 140 47 10 1 0 0 0
2304 1793 1291 825 443 187 57 11 1 0 0
5120 4097 3084 2116 1268 630 244 68 12 1 0

对于点 \(i , j\) 来说, 答案是 \(\frac{dp_{i , j}}{2^{i - 1}} \times K\)

我们考虑点 \((i , j)\) , 使他用第 \(0\) 列表示出来,我们摆出来一个杨辉三角,来看看:

  1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
1 5 10 10 5 1

我们能够发现,将 \(i , j\) 看做 \(0 , 0\) 他下面的选的次数可以用杨辉三角的某个点表示。

并且为(点设为 \((n , n - m)\) , 与上面我们的dp做法衔接一下 ):

\[ans = \sum_{i = 1}^{n - 1}C^{n - m - 1}_{n - i - 1} \times dp_{i , 0}\times K
\]

注意两个 -1 , 关于这个位置为啥要减一,这里解释一下:

对于当已经到 \(0\) 时,在杨辉三角中的位置依然可能有上一位转过来,但是两行的首位是没有关系的,那么他只能够由他的左上方的点转移过来,就相当于左上方的值了。

code

114514
#include <bits/stdc++.h>
#define int long long
using namespace std ;
const int N = 2e6 + 10 ;
const int mod = 1e9 + 7 ; int n , T , m , K ;
int now[N] ; inline int read() {
int x = 0 , f = 1 ;
char c = getchar() ; while ( c < '0' || c > '9' ) { if ( c == '-' ) f = -f ; c = getchar() ;
} while ( c >= '0' && c <= '9' ) {
x = x * 10 + c - '0' ;
c = getchar() ;
} return x * f ;
} namespace Combination {
int D[N] ; int nueyong[N] , sum_neo[N] , sum[N] ; inline void lear_neoyong() { sum_neo[0] = sum_neo[1] = 1 ;
nueyong[1] = 1 ; nueyong[0] = 1 ;
sum[0] = sum[1] = 1 ; for( int i = 2 ; i < N ; ++ i ) { int p = mod ;
int k = p / i ;
nueyong[i] = ( k * ( p - nueyong[p % i] ) ) % p ;
sum_neo[i] = ( nueyong[i] * sum_neo[i - 1] ) % p ;
sum[i] = ( i * sum[i - 1] ) % p ; }
} int Quick_Pow( int alpha , int beta )
{
int ans = 1 ; while ( beta > 0 ) { if( beta & 1 ) ans = ( ans * alpha ) % mod ; beta >>= 1 ; alpha = ( alpha * alpha ) % mod ;
} return ans ;
} int Regular_C_of_Pow_Class( int n , int m ) {
int alpha = 1 , beta = 1 , rereturn = 0 ; if( m <= n && n >= 0 && m >= 0 ) { for( int i = n - m + 1 ; i <= n ; ++ i ) {
alpha = ( alpha * i ) % mod ; }
for( int i = 1 ; i <= m ; ++ i ) {
beta = ( beta * i ) % mod ;
} rereturn = ( alpha * Quick_Pow( beta , mod - 2 ) ) % mod ;
return rereturn ; } else return 0 ; } inline int jc( int x ) {
return sum[x] ;
} inline int neo_jc( int x ) { if ( x == 0 ) return 1 ; return sum_neo[x] ;
} int Regular_C_of_Inv( int n , int m ) {
return ( ( ( jc( n ) * neo_jc( n - m ) ) % mod ) * neo_jc( m ) ) % mod ;
} int C_Lucas_Using_Inv( int n , int m ) { if ( m > n ) return 0 ; if ( m == 0 ) return 1 ; return ( Regular_C_of_Inv( n % mod , m % mod ) * C_Lucas_Using_Inv( n / mod , m / mod ) ) % mod ;
} int C_Lucas_Using_Pow( int n , int m ) { if( m == 0 ) return 1 ; return ( Regular_C_of_Pow_Class( n % mod , m % mod ) * C_Lucas_Using_Pow( n / mod , m / mod ) ) % mod ;
} void Asking_for_Derangement() { D[0] = 1 ;
D[1] = 0 ;
D[2] = 1 ;
for( int i = 3 ; i < N ; ++ i ) { D[i] = ( i - 1 ) * ( D[i - 1] + D[i - 2] ) % mod ; }
} inline void Cleared() {
memset( D , 0 , sizeof(D) ) ;
memset( sum_neo , 0 , sizeof(sum_neo) ) ;
memset( sum , 0 , sizeof(sum) ) ;
memset( nueyong , 0 , sizeof(nueyong) ) ;
}
} ;
using namespace Combination ; inline int Regular_Quick_Pow( int a , int b ) {
int ans = 1 ; while ( b > 0 ) { if ( b & 1 ) ans = ( ans * a ) % mod ; b >>= 1 ; a = ( a * a ) % mod ;
} return ans ;
} signed main() { #ifndef ONLINE_JUDGE
freopen( "1.in" , "r" , stdin ) ;
freopen( "1.out" , "w" , stdout ) ;
#endif T = read() ;
lear_neoyong() ;
for ( int i = 1 ; i <= 1e6 * 2 ; ++ i ) {
now[i] = ( i * Regular_Quick_Pow( 2 , i - 1 ) ) % mod ;
} while ( T -- ) { n = read() , m = read() , K = read() ; if ( n - m == 0 ) {
cout << ( n * K ) % mod << '\n' ;
continue ;
} int ans = 0 ;
for ( int i = 1 ; i <= n - 1 ; ++ i ) { ans = ( ans + C_Lucas_Using_Inv( n - i - 1 , n - m - 1 ) * now[i] ) % mod ;
} cout << ( ( ( K * ans ) % mod ) * Regular_Quick_Pow( Regular_Quick_Pow( 2 , n - 1 ) , mod - 2 ) ) % mod << '\n' ;
}
}

结尾撒花 \(\color{pink}{✿✿ヽ(°▽°)ノ✿}\)

Game on Sum--组合数学--DP的更多相关文章

  1. 【uoj#22】[UR #1]外星人 组合数学+dp

    题目描述 给你一个长度为 $n$ 的序列 $\{a_i\}$ 和一个数 $x$ ,对于任意一个 $1\sim n$ 的排列 $\{p_i\}$ ,从 $1$ 到 $n$ 依次执行 $x=x\ \tex ...

  2. 【bzoj1925】[Sdoi2010]地精部落 组合数学+dp

    题目描述 传说很久以前,大地上居住着一种神秘的生物:地精. 地精喜欢住在连绵不绝的山脉中.具体地说,一座长度为 N 的山脉 H可分 为从左到右的 N 段,每段有一个独一无二的高度 Hi,其中Hi是1到 ...

  3. UVA 10891 Game of Sum(DP)

    This is a two player game. Initially there are n integer numbers in an array and players A and B get ...

  4. HDU 1003 Max Sum --- 经典DP

    HDU 1003    相关链接   HDU 1231题解 题目大意:给定序列个数n及n个数,求该序列的最大连续子序列的和,要求输出最大连续子序列的和以及子序列的首位位置 解题思路:经典DP,可以定义 ...

  5. UVALive 7143 Room Assignment(组合数学+DP)(2014 Asia Shanghai Regional Contest)

    题目链接:https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&category=6 ...

  6. HDU-4532 湫秋系列故事——安排座位 组合数学DP

    题意:有来自n个专业的学生,每个专业分别有ai个同学,现在要将这些学生排成一行,使得相邻的两个学生来自不同的专业,问有多少种不同的安排方案. 分析:首先将所有专业的学生视作一样的,最后再乘以各自学生的 ...

  7. hdu 1003 Max sum(简单DP)

    Max Sum Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Problem ...

  8. UVA - 10891 Game of Sum 区间DP

    题目连接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=19461 Game of sum Description This ...

  9. Codeforces Codeforces Round #319 (Div. 2) B. Modulo Sum 背包dp

    B. Modulo Sum Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/577/problem/ ...

  10. POJ 2479-Maximum sum(线性dp)

    Maximum sum Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 33918   Accepted: 10504 Des ...

随机推荐

  1. 我对《RAG/大模型/非结构化数据知识库类产品》技术架构的思考、杂谈

    1.前言 在6.28/29的稀土掘金开发者大会RAG专场上,我们公司CEO员外代表TorchV分享了我们在<RAG在企业应用中落地的难点与创新> 其中最后分享了两个观点: AI在应用场景落 ...

  2. Spring Reactor基本介绍和案例

    1. Reactor 对比 1.1 Reactor 线程模型 Reactor 线程模型就是通过 单个线程 使用 Java NIO 包中的 Selector 的 select()方法,进行监听.当获取到 ...

  3. 1. CMake 概述

    1. CMake 概述 CMake 可以用来构建C/C++工程,可以跨平台.允许开发者指定整个工程的编译流程 在CMake 没有出来之前,开发者需要手写 makefile,但是不同平台下的 makef ...

  4. oeasy教您玩转vim - 65 - # 批处理操作

    ​ 批处理操作 回忆上次 我们上次参数列表 arguments list 所谓参数列表指的是 vim 打开的 参数列表 参数会加载到内存中成为 buffer 参数的控制 :arga filename ...

  5. Django model 层之Models与Mysql数据库小结

    Django model 层之Models与Mysql数据库小结 by:授客 QQ:1033553122 测试环境: Python版本:python-3.4.0.amd64 下载地址:https:// ...

  6. 智能家居如何把老款定频空调变成智能“变频”空调#米家#智能家居#HA

    背景 最近长沙的天气暴热,室内达到了34-35度,天气预报最高温度上了40度,这么酷热的天气,离开了空调,基本上就是一身汗,全身湿透,特别难受,然后不得不开启家里的一台将近10年的老式定频空调,输入功 ...

  7. (六)Redis 消息队列 List、Streams

    Redis 适合做消息队列吗?有什么解决方案?首先要明白消息队列的消息存取需求和工作流程. 1.消息队列 我们一般把消息队列中发送消息的组件称为生产者,把接收消息的组件称为消费者,下图是一个通用的消息 ...

  8. RHCA rh442 001 调优本质 调优方法 监控

    调优是一种感知 调优按照成本和性能 一.架构及调优 二.代码及调优 三.配置类调优 从调优效果和成本成正比 设计电商,日访问百万级,未来可能千万级 数据库 系统 服务器多少台 缓存 appache,n ...

  9. 【RabbitMQ】03 订阅模式

    Pub / Sub 订阅模式 特点是 一条消息可以给多个消费者接收了 首先创建订阅模式生产者发生一些代码变动: package cn.dzz.pubSub; import com.rabbitmq.c ...

  10. URDF使用语法【万字解析赶紧码住】 —— 机器人统一描述文件格式(Unified Robot Description Format)

    原文地址: https://zhuanlan.zhihu.com/p/665269288 具体内容略,请参照原文.