• bzoj2751--[HAOI]2012容易题--组合(乘法原理)


    Description


    为了使得大家高兴,小Q特意出个自认为的简单题(easy)来满足大家,这道简单题是描述如下:
    有一个数列A已知对于所有的A[i]都是1~n的自然数,并且知道对于一些A[i]不能取哪些值,我们定义一个数列的积为该数列所有元素的乘积,要求你求出所有可能的数列的积的和 mod 1000000007的值,是不是很简单呢?呵呵!

    Input


    第一行三个整数n,m,k分别表示数列元素的取值范围,数列元素个数,以及已知的限制条数。
    接下来k行,每行两个正整数x,y表示A[x]的值不能是y。

    Output

    一行一个整数表示所有可能的数列的积的和对1000000007取模后的结果。如果一个合法的数列都没有,答案输出0。

    Sample Input

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

    Sample Output

    90

    样例解释
    A[1]不能取1
    A[2]不能去2、3
    A[4]不能取3
    所以可能的数列有以下12种
      数列    积
    2 1 1 1   2
    2 1 1 2   4
    2 1 2 1   4
    2 1 2 2   8
    2 1 3 1   6
    2 1 3 2  12
    3 1 1 1   3
    3 1 1 2   6
    3 1 2 1   6
    3 1 2 2  12
    3 1 3 1   9
    3 1 3 2  18

    HINT

    数据范围

    30%的数据n<=4,m<=10,k<=10

    另有20%的数据k=0

    70%的数据n<=1000,m<=1000,k<=1000

    100%的数据 n<=109,m<=109,k<=105,1<=y<=n,1<=x<=m

    题解:

      首先假设如果k=0。

      容易发现没有限制时,a[i]的每个位置都可以取1~n的任何一个数字,而因为a数组只有m个位置,所以显然此时

      那如果k!=0,就代表a[i]的当前位置有限制数字时,它只能取1~n中限制数字以外的。

      所以计算积时,a[i]贡献给ans的只有这么多。

      于是我们先算出不被限制的位置的乘积,也就是  其中cnt表示总共有多少位置被限制了(cnt不一定等于k)

      对于被限制的位置,我们判一下重,一个位置可能被多个数字限制。

      最后被限制的和不被限制的相乘即为所求。

     1 #include<iostream>
     2 #include<cmath>
     3 #include<cstdio>
     4 #include<algorithm>
     5 #define ll long long
     6 using namespace std;
     7 const int mod=1000000007;
     8 const int maxn=100009;
     9 ll sum[maxn];
    10 struct data
    11 {
    12     ll x,y;
    13 }a[maxn];
    14 bool cmp(data a1,data a2)
    15 {
    16     if(a1.x==a2.x)
    17         return a1.y<a2.y;
    18     else
    19         return a1.x<a2.x;
    20 }
    21 int poww(int x,int y,int mod)
    22 {
    23     int ret=1;
    24     while(y)
    25     {
    26         if(y&1)
    27             ret=1ll*ret*x%mod;
    28         x=1ll*x*x%mod;
    29         y>>=1;
    30     }
    31     return ret;
    32 }
    33 int main()
    34 {
    35     ll ans=0;
    36     int n,m,k;
    37     cin>>n>>m>>k;
    38     ll sgm=(1ll*n*(n+1)>>1)%mod;
    39     for(int i=1;i<=k;i++)
    40     {
    41         cin>>a[i].x>>a[i].y;
    42     }
    43     sort(a+1,a+k+1,cmp);
    44     int cnt=0;
    45     for(int i=1;i<=k;i++)
    46     {
    47         if(a[i].x!=a[i-1].x)
    48             sum[++cnt]=sgm;//判重
    49         else
    50         {
    51             if(a[i].y==a[i-1].y)//防止多次减同一个限制条件
    52             continue;
    53         }
    54         sum[cnt]=(sum[cnt]-a[i].y+mod)%mod;//减去被限制的数
    55     }
    56     ans+=poww(sgm,m-cnt,mod);
    57     for(int i=1;i<=cnt;i++)
    58     {
    59         ans=(ans*sum[i]+mod)%mod;//乘上有限制的情况
    60     }
    61     cout<<ans<<endl;
    62     return 0;
    63 }
    View Code
  • 相关阅读:
    第一次作业-准备篇
    个人作业——软件工程实践总结
    团队作业第二次—项目选题报告
    软工实践第三次作业(结对第二次作业)
    软工实践第二次作业(结对第一次作业)
    第一次作业-准备篇
    软工实践|个人作业——软件工程实践总结作业
    软工实践|团队作业第二次—项目选题报告
    软工实践|结对第二次—文献摘要热词统计及进阶需求
    软工实践|结对第一次—原型设计(文献摘要热词统计)
  • 原文地址:https://www.cnblogs.com/Beckinsale/p/7488874.html
Copyright © 2020-2023  润新知