zoukankan      html  css  js  c++  java
  • [haoi2012]容易题(数论+容斥的思想)

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

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

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

    样例输入 Sample Input
    3 4 5
    1 1
    1 1
    2 2
    2 3
    4 3

    样例输出 Sample Output
    90 

    时间限制 Time Limitation
    1s 

    注释 Hint
    样例解释
    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
    数据范围
    30%的数据n<=4,m<=10,k<=10
    另有20%的数据k=0
    70%的数据n<=1000,m<=1000,k<=1000
    100%的数据 n<=10^9,m<=10^9,k<=10^5,1<=y<=n,1<=x<=m

    来源 Source
    haoi2012 

        思路:因为这个数列A[i]的取值范围是1~n,所以显然可以发现这个数位上的数字和为(1+n)*n/2。然后又可以发现这个数列最终的乘积就为各个数位上可选数之和的乘积,自己试一下便可以发现。因为k的范围比较小,所以直接先算出这些有限制的位的乘积,然后在用快速幂算出剩余位置的乘积,最后相乘即可。

    注意:记得所有变量全用long long,如果一个数x要取模k,那么你可以这样写(x%k+k)%k。这样就可以防止x为负数的时候取模出错(反正最后改了这两个就A了,不然只能过小数据)

    代码如下:

    #include<iostream>
    #include<cstring>
    #include<algorithm>
    #include<cstdio>
    #include<cmath>
    #include<string>
    #define K 1000000007 
    #define ll long long
    using namespace std;
    inline ll read()
    {
        char ch=getchar();
        ll x=0,f=1;
        while(ch>'9'||ch<'0')
        {
            if(ch=='-')
                f=-1;
            ch=getchar();
        }
        while(ch>='0'&&ch<='9')
        {
            x=x*10+ch-'0';
            ch=getchar();
        }
        return x*f;
    }
    ll n,m,k;
    ll M;
    struct shadow
    {
        ll x,y;
    }a[101000],c[101000],b[106000];
    ll d[101000];
    bool mycmp(shadow x,shadow y)
    {return x.x==y.x?x.y<y.y:x.x<y.x;}
    ll work(ll p)
    {
        ll ans=1;
        ll temp=p,s=M;
        while(temp!=0)
        {
            if(temp%2==1)
            {
                ans*=s;
                ans=(ans%K+K)%K;
            }
            ans%=K;
            temp/=2;
            s=(s*s%K+K)%K;
        }
        return ans;
    }
    int main()
    {
        memset(c,0,sizeof(c));
        n=read();m=read();k=read();
        M=(1+n)*n/2%K;
        for(ll i=1;i<=k;i++)
        {
            a[i].x=read();
            a[i].y=read();
            c[i].x=a[i].x;
            c[i].y=a[i].y;
        }
        sort(a+1,a+1+k,mycmp);
        sort(c+1,c+1+k,mycmp);
        ll l=0;
        for(ll i=1;i<=k;i++)
        {
            if(c[i].x==c[i+1].x&&c[i].y==c[i+1].y)
                continue;
            b[++l]=c[i];
        }
        /*for(ll i=1;i<=l;i++)
            cout<<b[i].x<<' '<<b[i].y<<endl;*/
        for(ll i=1;i<=l;i++)
            d[i]=M;
        ll t=0;
        for(ll i=1;i<=l;i++)
        {
            bool f=false;
            if(b[i].x==b[i+1].x)
            {
                t++;
                while(b[i].x==b[i+1].x)
                {
                    d[t]-=b[i].y;
                    d[t]=(d[t]%K+K)%K;
                    i++;
                    f=true;
                }
                if(f)//这个就是如果第i位和第i+1位相同,再把第i+1位也减去
                {
                    d[t]-=b[i].y;
                    d[t]=(d[t]%K+K)%K;
                }
            }
            else
                d[++t]-=b[i].y;
        }
        ll h=work(m-t);
        ll ans=1;
        for(ll i=1;i<=t;i++)
            ans*=d[i],ans%=K;
        ans=(ans*h%K+K)%K;
        cout<<ans<<endl;
        return 0;
    }
    (づ ̄3 ̄)づ╭❤~
  • 相关阅读:
    Linux如何通过命令查看日志文件的某几行(中间几行或最后几行)
    将生成200 个激活码(或者优惠券)保存到 oracle关系型数据库中
    将你的 QQ 头像(或者微博头像)右上角加上红色的数字,类似于微信未读信息数量那种提示效果
    面试笔试题:多表关联的update语句、将in中的查询条件按顺序输出和SQL语句增加列、修改列、删除列
    sql中级到高级
    Linux常用命令
    类的特殊成员方法
    正则表达式的方法匹配规则
    启动ecilpse 报错an error has occurred. see the log file
    访问修饰符
  • 原文地址:https://www.cnblogs.com/lcyhaha/p/7590189.html
Copyright © 2011-2022 走看看