zoukankan      html  css  js  c++  java
  • [HAOI2012] 容易题

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

                           --by洛谷;

    http://daniu.luogu.org/problem/show?pid=2220



    简单题?呵呵

    首先,她有个公式

    我们先假设k=0;

    ai为a位的可能;bi为b位的可能;ci为c位的可能...

    则:

    a1*b1*c1+a1*b1*c2+a1*b2*c1+a1*b2*c2+a2*b1*c1+a2*b1*c2+a2*b2*c1+a2*b2*c2;

    你提公因式嘛;

    a1*(b1*c1+b1*c2+b2*c1+b2*c2)+a2*(b1*c1+b1*c2+b2*c1+b2*c2);

    再提

    a1*[b1*(c1+c2)+b2*(c1+c2)]+a2*[b1*(c1+c2)+b2*(c1+c2)];

    a1*(b1+b2)*(c1+c2)+a2*(b1+b2)*(c1+c2);

    (a1+a2)*(b1+b2)*(c1+c2);

    再通过k的存在,对每位的可能减zi;

    (a1+a2-z1)*(b1+b2-z2)*(c1+c2-z3);

    然后每一位在k=0一样,即a1+a2=b1+b2=c1+c2=sum(n);

    (sum(n)-z1)*(sum(n)-z2)*(sum(n)-z3);

    所以,这叫简单题?

    就想预处理sum(n)然后O(n)乘,每次记得减z;

    然而O(n)也过不了——n=1e9。。。

    所以,这叫简单题?

    但是我们发现,k比较小,1e5;

    所以有限制的位置,小于等于1e5;

    我们可以先算她们,然后剩下的写一个快速幂;

    时间效率O(klogk+k+log(n-k));

    (因为有个sort);

    代码如下:

     1 #include<cstdio>
     2 #include<algorithm>
     3 #define mod 1000000007
     4 using namespace std;
     5 struct ss
     6 {
     7     int x,y;
     8 }a[100001];
     9 long long b[100001];
    10 
    11 bool cmp(ss a,ss b)
    12 {
    13     if(a.x==b.x)
    14         return a.y<b.y;
    15     return a.x<b.x;
    16 }
    17 long long sqr(long long ,int );
    18 
    19 int main()
    20 {
    21     int n,m,k;
    22     long long sz1=0;
    23     long long ans=1;
    24     int i,j,l;
    25     scanf("%d%d%d",&n,&m,&k);
    26     sz1=(long long)n*(n+1)/2%mod;
    27     for(i=1;i<=k;i++)
    28         scanf("%d%d",&a[i].x,&a[i].y);
    29     sort(a+1,a+k+1,cmp);
    30     j=0;
    31     for(i=1;i<=k;i++)
    32     {
    33         if(a[i].x!=a[i-1].x)
    34             b[++j]=a[i].y;
    35         else
    36             if(a[i].y!=a[i-1].y)
    37                 b[j]=(b[j]+a[i].y)%mod;
    38     }
    39     for(i=1;i<=j;i++)
    40         ans=(ans*(sz1-b[i]+mod))%mod;
    41     m=m-j;
    42     ans=(ans*sqr(sz1,m))%mod;
    43     printf("%lld",ans);
    44     return 0;
    45 }
    46 
    47 long long sqr(long long sz,int m)
    48 {
    49     long long ans=1;
    50     while(m)
    51     {
    52         if(m&1)
    53             ans=(ans*sz)%mod;
    54         sz=(sz*sz)%mod;
    55         m=m>>1;
    56     }
    57     return ans;
    58 }

    祝AC哟;

    Just close your eyes, you`ll be alright, no one can hurt you after you die.
  • 相关阅读:
    Justoj 2389: 拼接三角形 二分查找
    P4513 小白逛公园(线段树求区间最大子段和)
    勾股数
    费马大定理
    D1. Kirk and a Binary String (easy version)
    Find the median(线段树离散化+区间更新)
    String
    最小表示法
    扩展KMP模板(学习)
    K-th Closest Distance
  • 原文地址:https://www.cnblogs.com/nietzsche-oier/p/6223515.html
Copyright © 2011-2022 走看看