zoukankan      html  css  js  c++  java
  • 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分。

  • 相关阅读:
    Windows打开软件老是弹出无法验证发布者
    SpringMvc接受特殊符号参数被转义
    时代更替中的方正
    你应该知道的c# 反射详解
    C#使用System.Data.SQLite操作SQLite
    C# 动态调用WebService
    C# API: 生成和读取Excel文件
    11个强大的Visual Studio调试小技巧
    .Net 垃圾回收和大对象处理
    Visual Studio原生开发的10个调试技巧(一)
  • 原文地址:https://www.cnblogs.com/donkey2603089141/p/11416419.html
Copyright © 2011-2022 走看看