SSL P2676 数学math

题目大意:
小A得到了一个数列A,他告诉你这个数列中所有的A[i]都是1到n的自然数,并且告诉你对于一些A[i]不能取哪些值。无聊的你想要知道所有可能的数列的积的和。定义一个数列的积为这个数列所有数的乘机。由于答案太大,只要模10^9+7输出即可。

对于前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

题解:
快速幂+枚举:
我们找规律发现,
设到当前第i点乘积和的为sum[i],则到i+1个点,可以* 1,* 2,…… (n-1),*n
则sum[i]:=sum[i-1]*(1+2+……+n)

然后我们先用公式求出1~n的sum
则sum=(1+n)*n/2,2必定被整除
然后对于K个限制,我们排序以后,去重另外做,然后将剩下没变的M-X位,X是K个限制改变了的点的总数。
然后求 sum^(m-x)*对这X位的处理。
前者可以用快速幂求,后者直接暴力。
然后注意过程中的取模。

const
   modn=1000000007;

var
   c:array [0..100001,1..2] of longint;
   n,m,k,i,j,p:longint;
   ans,q,l:int64;

function qm(t:int64):int64;
begin
    exit(t mod modn);
end;

function ksm(a,b:int64):int64;
begin
    ksm:=1;
    while b<>0 do
    begin
        if b mod 2=1 then
           ksm:=qm(ksm*a);
        b:=b div 2;
        a:=qm(a*a);
    end;
end;

procedure qsort(l,r:longint);
var
    i,j,mid,kid:longint;
begin
    if l>=r then exit;
    mid:=c[(l+r) div 2,1];
    kid:=c[(l+r) div 2,2];
    i:=l; j:=r;
    repeat
          while (c[i,1]<mid) or ((c[i,1]=mid) and (c[i,2]<kid)) do inc(i);
          while (c[j,1]>mid) or ((c[j,1]=mid) and (c[j,2]>kid)) do dec(j);
          if i<=j then
          begin
               c[0]:=c[i];c[i]:=c[j];c[j]:=c[0];
               inc(i); dec(j);
          end;
    until i>j;
    qsort(i,r);
    qsort(l,j);
end;

begin
    readln(n,m,k);
    if (k>=n) and (k>=m) then
     if k>=n*m
       then begin
                writeln(0);
                halt;
            end;
    l:=qm(qm(qm(n+1)*n) div 2);
    ans:=1;
    for i:=1 to k do readln(c[i,1],c[i,2]);
    qsort(1,k);
    i:=1;
    while i<=k do
    begin
         dec(m);
         j:=1;
         while c[i,1]=c[i+j,1] do inc(j);
         q:=qm(l-c[i,2]+modn); j:=j-1;
         for p:=i+1 to i+j do
           if c[p,2]<>c[p-1,2] then q:=qm(q-c[p,2]+modn);
         ans:=qm(ans*q);
         i:=i+j+1;
    end;
    ans:=qm(ans*ksm(l,m));
    writeln(ans);
end.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值