yzoj P2349 取数 题解

题意

1到n个自然数中选k个自然数要求两两不相邻,问有多少种方法,模m

eg(1 3 5 )

又是一道打表规律题,正常解法dp可以通过前缀和优化到O(N* K)。另外我们可以重新定义F[I,J]表示从1到I中选择J个不连续数的方案数。通过考虑I选还是不选来进行状态转移。

1.如果不选I:则方案数为F[I-1,J];

2.如果选I:由于不能选相邻两个数,所以I-1不能选,则剩余的J-1个数只能在1到I-2中选,即F[I-2,J-1];

f[i][j]=f[i-1][j]+f[i-2][j-1] (j>1)

f[i][j]=1 (j==1) 边界条件

然而这样写只有70分

考虑找规律

过打表可以发现规律,当然我们也可以这样来考虑,为了保证所选K个数不连续,我们可以考虑先从N-(K-1)个数中选择K个数出来,这样选出来的是不能保证不连续的,但我们可以把该方案调整成合法方案,只要把第I(1<=I<=K)个数每个数加I-1,这样每个方案就一一对应于一个合法方案。所以答案为C(N-K+1,K)。如题目中样例,我们可以认为是C(4,3),从1到4中选3个数的方案跟从1到6中选3个不连续的方案是一一对应的,用上面的方法得到以下对应关系:

(1,2,3)<-> (1,3,5)

(1,2,4)<-> (1,3,6)

(1,3,4)<-> (1,4,6)

(2,3,4)<-> (2,4,6)

注意85%的数据N<=1000000,M=1000003,根据上面分析,答案Ans=(N-K+1)* (N-K) * ...* (N-2 * K+2)/(K * (K-1) ... 1 )mod M,我们可以先把分子即(N-K+1) * (N-K) * ...* (N-2* K+2)mod M的值计算出来记为a,同样把分母即K(K-1) ...* 1 mod M的值计算出来记为b,由于这里M=1000003是一个素数,所以Ans的答案是唯一的。我们可以枚举Ans再判断Ans* b mod M=a是否成立即可。时间复杂度为O(N+M),预计得分85分。

代码

#include<bits/stdc++.h>
using namespace std;
long long a=1,b=1,n,k,m;
int main(){
    scanf("%lld %lld %lld",&n,&k,&m);
    for(int i=1;i<=k;++i){
        a=a*(n-2*k+i+1)%m;
        b=(b*i)%m;
    }
    for(int ans=1;ans<m;++ans){
        if(((ans*b)%m)==a){
            printf("%d",ans);
            return 0;
        }
    }
    return 0;
}

正解

计算C(N-K+1,K)mod M,跟方法三同样先计算出分子分母对M的余数a和b,根据x=(x/y)* y可知:a=(Ans* b)mod m,再转化成Ans* b+m* P=a,其中b,m和a为已知,并且m为素数,这样就变成我们熟悉的a* x+b* y=c,用扩展GCD来求。时间复杂度为O(N)。预计得分:100分。

原文地址:https://www.cnblogs.com/donkey2603089141/p/11416419.html

时间: 2024-10-29 16:09:45

yzoj P2349 取数 题解的相关文章

洛谷 P1005 矩阵取数游戏 题解

此文为博主原创题解,转载时请通知博主,并把原文链接放在正文醒目位置. 题目链接:https://www.luogu.org/problem/show?pid=1005 题目描述 帅帅经常跟同学玩一个矩阵取数游戏:对于一个给定的n*m的矩阵,矩阵中的每个元素aij均为非负整数.游戏规则如下: 1.每次取数时须从每行各取走一个元素,共n个.m次后取完矩阵所有元素: 2.每次取走的各个元素只能是该元素所在行的行首或行尾: 3.每次取数都有一个得分值,为每行取数的得分之和,每行取数的得分 = 被取走的元

Noip2007矩阵取数游戏题解

题目描述 Description [问题描述] 帅帅经常跟同学玩一个矩阵取数游戏:对于一个给定的n?m的矩阵,矩阵中的每个元素ai,j均 为非负整数.游戏规则如下: 每次取数时须从每行各取走一个元素,共n个.m次后取完矩阵所有元素: 每次取走的各个元素只能是该元素所在行的行首或行尾: 每次取数都有一个得分值,为每行取数的得分之和,每行取数的得分=被取走的元素值?2i, 其中i表示第i 次取数(从1 开始编号): 游戏结束总得分为m次取数得分之和. 帅帅想请你帮忙写一个程序,对于任意矩阵,可以求出

【题解】CH Round #61 取数游戏

取数游戏 CH Round #61 - 「Adera 10」冬令营热身赛 描述 SJY和CYF在玩一个取数游戏.他们将1~n分别写在n张纸上,随机排成一排,约定SJY先取,只能取走最边上的两张纸之一,然后CYF取:以此循环下去,取到1的人获胜.假设SJY和CYF足够聪明,求SJY获胜的概率. 输入 一个整数n 输出 SJY获胜的概率,保留最简分数形式(若为1,则输出1/1:若为0,则输出0/1). 样例 样例输入1 2 样例输出1 1/1 样例输入2 3 样例输出2 2/3 数据范围与约定 40

【日常学习】【区间DP+高精】codevs1166 矩阵取数游戏题解

题目来自NOIP2007TG3 如果在考场上我现在已经歇菜了吧 今天一整天的时间全部投在这道题上,收获不小. 先上题目 题目描述 Description [问题描述] 帅帅经常跟同学玩一个矩阵取数游戏:对于一个给定的n*m 的矩阵,矩阵中的每个元素aij均 为非负整数.游戏规则如下: 1. 每次取数时须从每行各取走一个元素,共n个.m次后取完矩阵所有元素: 2. 每次取走的各个元素只能是该元素所在行的行首或行尾: 3. 每次取数都有一个得分值,为每行取数的得分之和,每行取数的得分= 被取走的元素

hdu 1565 方格取数(2)(网络流之最大点权独立集)

题目链接:hdu 1565 方格取数(2) 题意: 有一个n*m的方格,每个方格有一个数,现在让你选一些数.使得和最大. 选的数不能有相邻的. 题解: 我们知道对于普通二分图来说,最大独立点集 + 最小点覆盖集 = 总点数,类似的,对于有权的二分图来说,有: 最大点权独立集 + 最小点权覆盖集 = 总点权和, 这个题很明显是要求 最大点权独立集 ,现在 总点权 已知,我们只要求出来 最小点权覆盖集 就好了,我们可以这样建图, 1,对矩阵中的点进行黑白着色(相邻的点颜色不同),从源点向黑色的点连一

1475: 方格取数

1475: 方格取数 Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 578  Solved: 309[Submit][Status][Discuss] Description 在一个n*n的方格里,每个格子里都有一个正整数.从中取出若干数,使得任意两个取出的数所在格子没有公共边,且取出的数的总和尽量大. Input 第一行一个数n:(n<=30) 接下来n行每行n个数描述一个方阵 Output 仅一个数,即最大和 Sample Input 2 1 2

[CH Round #61] 取数游戏

描述 SJY和CYF在玩一个取数游戏.他们将1~n分别写在n张纸上,随机排成一排,约定SJY先取,只能取走最边上的两张纸之一,然后CYF取:以此循环下去,取到1的人获胜.假设SJY和CYF足够聪明,求SJY获胜的概率. 输入 一个整数n 输出 SJY获胜的概率,保留最简分数形式(若为1,则输出1/1:若为0,则输出0/1). 样例 样例输入1 2 样例输出1 1/1 样例输入2 3 样例输出2 2/3 数据范围与约定 40%的数据,0<n≤7. 70%的数据,0<n≤1000. 100%的数据

P1288 取数游戏II

题目描述 有一个取数的游戏.初始时,给出一个环,环上的每条边上都有一个非负整数.这些整数中至少有一个0.然后,将一枚硬币放在环上的一个节点上.两个玩家就是以这个放硬币的节点为起点开始这个游戏,两人轮流取数,取数的规则如下: (1)选择硬币左边或者右边的一条边,并且边上的数非0: (2)将这条边上的数减至任意一个非负整数(至少要有所减小): (3)将硬币移至边的另一端. 如果轮到一个玩家走,这时硬币左右两边的边上的数值都是0,那么这个玩家就输了. 如下图,描述的是Alice和Bob两人的对弈过程,

BZOJ1978: [BeiJing2010]取数游戏 game

1978: [BeiJing2010]取数游戏 game Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 650  Solved: 400[Submit][Status] Description 小 C 刚学了辗转相除法,正不亦乐乎,这小 P 又出来捣乱,给小 C 留了个 难题. 给 N 个数,用 a1,a2…an来表示.现在小 P 让小 C 依次取数,第一个数可以 随意取.假使目前取得 aj,下一个数取ak(k>j),则ak必须满足gcd(aj,a