zoukankan      html  css  js  c++  java
  • P2220 [HAOI2012]容易题[小学数学]

    题目描述

    为了使得大家高兴,小Q特意出个自认为的简单题(easy)来满足大家,这道简单题是描述如下:

    有一个数列A已知对于所有的A[i]都是1~n的自然数,并且知道对于一些A[i]不能取哪些值,我们定义一个数列的积为该数列所有元素的乘积,要求你求出所有可能的数列的积的和 mod 1000000007的值,是不是很简单呢?呵呵!

    解析

    标签里面数论是骗人的(雾),难道是因为有个取模吗???

    这题还是很简单的,首先观察数据范围,发现k比较小,那我们就对它做文章。

    我们不妨先求出没有限制条件下的总和,再减去限制条件造成的影响,这样复杂度就与k有关了。

    假设(p)为除了位置(i)其余位置的积,那么

    (ans=1*p+2*p+cdots+n*p=(frac{n(n+1)}{2})*p)

    对于任意位置,显然都是这个东西。

    那么(ans={(frac{n(n+1)}{2})}^m)

    或者理解作一堆项相乘,(ans=(1+2+cdots+n)*(1+2+cdots+n)*cdots)

    总共有(m)项,就变成上面那个东西。

    然后我们考虑限制条件。

    先对限制按位置排序,对于一个位置(i)的所有限制条件,若它们的和为(sum),很容易看出它们剔除的答案为(sum*{(frac{n(n+1)}{2})}^{m-i-1}*now)。其中(now)为剔除过限制条件的(1sim i-1)的积。(now)的初始值是1,每次剔除都乘上(frac{n(n+1)}{2}-sum)

    而且,由于每次剔除的位置对最后结果无影响,离散化。

    复杂度(O(klogm+klogk))

    我的代码写的比较鬼畜,还请各位大佬见谅QWQ。

    参考代码

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<string>
    #include<cstdlib>
    #include<queue>
    #include<vector>
    #include<set>
    #define INF 0x3f3f3f3f
    #define PI acos(-1.0)
    #define N 100010
    #define MOD 2520
    #define E 1e-12
    #define ll long long
    #define mod 1000000007
    #define div 500000004
    using namespace std;
    inline int read()
    {
    	int f=1,x=0;char c=getchar();
    	while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    	while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
    	return x*f;
    }
    ll n,m,k,sum[N];
    set<int> s[N];
    struct node{
    	int pos,x;
    	inline bool operator<(const node &a)const{
    		return a.pos>pos;
    	}
    }a[N];
    inline ll qp(ll a,ll b){ll ans=1;for(;b;b>>=1){if(b&1)ans=(ans*a)%mod;a=(a*a)%mod;}return ans%mod;} 
    int main()
    {
    	n=read(),m=read(),k=read();
    	for(int i=1;i<=k;++i)
    		a[i].pos=read(),a[i].x=read();
    	sort(a+1,a+k+1);
    	int cnt=1,pos=a[1].pos;
    	for(int i=1;i<=k;++i){
    		if(pos==a[i].pos){
    			if(s[cnt].find(a[i].x)!=s[cnt].end()) continue;
    			s[cnt].insert(a[i].x),sum[cnt]=(sum[cnt]%mod+a[i].x%mod)%mod;
    		}
    		else s[++cnt].insert(a[i].x),sum[cnt]=(sum[cnt]%mod+a[i].x%mod)%mod;
    		pos=a[i].pos;
    	}//脑抽写的set离散化
    	ll tmp=(n%mod*(n+1)%mod*div%mod)%mod;
    	ll ans=qp(tmp,m)%mod;
    	ll now=1;
    	for(int i=1;i<=cnt;++i){
    		ans=(ans%mod-sum[i]%mod*qp(tmp,m-i)%mod*now%mod+2*mod)%mod;
    		now=(now%mod*(tmp%mod-sum[i]%mod+2*mod)%mod)%mod;
    	}
    	printf("%lld
    ",ans%mod);
    	return 0;
    }
    
  • 相关阅读:
    训练赛(28)—— 计蒜客 45724 Jumping Frog
    训练赛(28)—— 计蒜客 45725 Fujiyama Thursday
    centos上libreoffice+unoconv安装步骤,实现word转pdf
    PhantomJS linux系统下安装步骤及使用方法(网页截屏功能)
    knockout应用开发指南(完整版)
    git 创建版本库
    保留json字符串中文的函数,代替json_encode
    微信公众平台开发接口PHP SDK完整版(转载)
    find_in_set()
    NuSOAP与PHPRPC比较(转)
  • 原文地址:https://www.cnblogs.com/DarkValkyrie/p/11794173.html
Copyright © 2011-2022 走看看