zoukankan      html  css  js  c++  java
  • HDU 4869 Turn the pokers (2014 Multi-University Training Contest 1)

    Turn the pokers

    Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
    Total Submission(s): 1064    Accepted Submission(s): 398


    Problem Description
    During summer vacation,Alice stay at home for a long time, with nothing to do. She went out and bought m pokers, tending to play poker. But she hated the traditional gameplay. She wants to change. She puts these pokers face down, she decided to flip poker n times, and each time she can flip Xi pokers. She wanted to know how many the results does she get. Can you help her solve this problem?
     
    Input
    The input consists of multiple test cases. 
    Each test case begins with a line containing two non-negative integers n and m(0<n,m<=100000). 
    The next line contains n integers Xi(0<=Xi<=m).
     
    Output
    Output the required answer modulo 1000000009 for each test case, one per line.
     
    Sample Input
    3 4 3 2 3 3 3 3 2 3
     
    Sample Output
    8 3
    Hint
    For the second example: 0 express face down,1 express face up Initial state 000 The first result:000->111->001->110 The second result:000->111->100->011 The third result:000->111->010->101 So, there are three kinds of results(110,011,101)

     

    果然又是一道神题目,用到的知识点真心多且有用。
     
    快速幂+费马小定理+巧妙的思路
     
    费马小定理:假如p是质数,且(a,p)=1,那么 a^(p-1) ≡1(mod p)因此 a * a^(p-2)  ≡1(mod p),即 a的乘法逆元是a^(p-2)
    因此题目需要求组合数:( n!/m!(n-m)! ) mod p =[ n! mod p ]*[ (m! mod p)^(p-2) mod p]*[ ((n-m)! mod p)^(p-2) mod p] mod p
     
    多搞几个数据,可以发现,只需找到最少翻动牌个数与最多翻动牌个数即可,中间的状态是连续的,剩下就是排列的问题了。
    因为每次翻一张牌,则正面增加1,反面减1,因此翻动的牌数是偶数变化的,又翻的牌可以随机,所以其最多与最少翻动牌数中间每隔一个都是允许出现的情况。
     
    官方题解:

    最终的结果一定是连续出现的,只需要求出最终的区间。

    因为如果对同一张牌进行两次操作,牌的状态不改变。故牌的翻转次数一定是减少偶数次。如果所有数的和是奇数,那么最终结果也一定是奇数。同理,偶数也是一样的。

    所以只要递推求出最后的区间,计算sumCxim)(i=012。。。)),m是总牌数,xi是在区间内连续的奇数或偶数,在模10^9+9就是最终的答案。

    #include <cstdio>
    #include <iostream>
    #include <cmath>
    #define Mod 1000000009
    #define max(x,y) ((x)>(y)?x:y)
    #define min(x,y) ((x)<(y)?x:y)
    using namespace std;
    long long J[100005];
    int n,m,a[100005],l,r,nl,nr;
    void Predo(){
        J[0]=1;
        for(int i=1;i<=100000;i++)
            J[i]=(J[i-1]*i)%Mod;
    }
    long long Q(long long a,long long p){
        int e[33],k=0;
        while(p){
            e[k++]=p%2;
            p=p/2;
        }
        long long tmp=1;
        for(int i=k-1;i>=0;i--)
            if(e[i]) tmp=((tmp*tmp)%Mod*a)%Mod;
            else tmp=(tmp*tmp)%Mod;
        return tmp;
    }
    long long C(int n,int m){
        return ((J[n]*Q(J[m],Mod-2))%Mod*Q(J[n-m],Mod-2))%Mod;
    }
    int main()
    {
        Predo();
        while(scanf("%d%d",&n,&m)!=EOF){
            for(int i=0;i<n;i++){
                scanf("%d",&a[i]);
            }
            int l=r=a[0];
            for(int i=1;i<n;i++){
                nl=min(abs(l-a[i]),abs(r-a[i]));
                if(l<=a[i]&&a[i]<=r){
                    if((a[i]-l)%2==0) nl=0;
                    else nl=1;
                }
                nr=max(l+a[i]<=m?l+a[i]:2*m-l-a[i] , r+a[i]<=m?r+a[i]:2*m-r-a[i]);
                if(m-r<=a[i]&&a[i]<=m-l){
                    if((a[i]-(m-r))%2==0) nr=m;
                    else nr=m-1;
                }
                l=nl;
                r=nr;
            }
            long long ans=0;
            for(int i=l;i<=r;i=i+2)
                ans=(ans+C(m,i))%Mod;
            printf("%lld
    ",ans);
        }
        return 0;
    }
  • 相关阅读:
    实验十四 团队项目评审&个人学习总结
    实验四 附加实验项目互评
    201671010401 包稚潼+《英文文本统计分析》结队项目报告
    201671010401包稚潼 实验二 词频统计软件项目报告
    201671010401包稚潼 实验三作业互评与改进
    阅读《构建之法》提出的相关问题
    201671010404+陈润菊 实验十四 团队项目评审课程&学习总结
    201671010404+陈润菊 实验四 附加作业-项目互评
    201671010404+陈润菊 实验四《英文文本统计分析》结对项目报告
    201671010404+陈润菊 实验二软件工程项目
  • 原文地址:https://www.cnblogs.com/Mathics/p/3866938.html
Copyright © 2011-2022 走看看