zoukankan      html  css  js  c++  java
  • 题目分享N 二代目

    题意:一个长度为m的序列,每个数能取1-n的值,有k个限制x,y表示a[x]!=y,求出所有可能的数列的积的和 mod 1000000007的值

    分析:很容易能想到,在没有限制的情况下,总和应该是(n*(n+1)/2)^m

    推导也很简单,比如我要在n-1的基础上再加上第n个数,这个数在之前数p的基础上还可以取1-n的数

    也就是p*1+p*2+...+p*n,也就是p*n*(n+1)/2,也就是说每增加一个数,结果就会乘以n*(n+1)/2

    那么剩下就很好办了

    用一个map记录是否有重复的限制出现,

    用一个vector记录被限制的位数有几个,分别被限制多少

    再用一个map防止vector里有重复的位置出现,

    最后统计一遍结果,再加一个快速幂即可

    代码:

    #include<cstdio>
    #include<map>
    #include<vector>
    using namespace std;
    
    #define ll long long
    
    const int mod=1e9+7;
    
    vector<int> q;
    map<int,ll> num;
    map<pair<int,int>,bool> mapp;
    
    ll pow(ll a,int b)
    {
        ll now=a,ans=1ll;
        while(b)
        {
            if(b&1) ans*=now,ans%=mod;
            b>>=1,now*=now,now%=mod;
        }
        return ans;
    }
    
    int main()
    {
        int n,m,k,x,y;
        scanf("%d%d%d",&n,&m,&k);
        while(k--)
        {
            scanf("%d%d",&x,&y);
            if(!num[x]) q.push_back(x);
            if(mapp[make_pair(x,y)]) continue;
            mapp[make_pair(x,y)]=1;
            num[x]+=(ll)y;
        }
        ll n2=(ll)n*(n+1)/2;
        ll ans=1;
        for(int i=0;i<q.size();i++) ans*=(n2-num[q[i]])%mod,ans%=mod;
        printf("%lld",ans*pow(n2%mod,m-q.size())%mod);
        return 0;
    }
  • 相关阅读:
    团队冲刺个人总结第二天
    Gym
    Codeforces Round #162 (Div. 2) A~D 题解
    Wormholes 虫洞 BZOJ 1715 spfa判断负环
    修剪草坪 单调队列优化dp BZOJ2442
    没有上司的舞会 树形dp
    餐巾计划问题 费用流
    最小路径覆盖问题 最大流
    [JSOI2007]麻将 模拟 BZOJ1028
    CF702F T-Shirts FHQ Treap
  • 原文地址:https://www.cnblogs.com/lin4xu/p/12873480.html
Copyright © 2011-2022 走看看