• 51nod1026 矩阵中不重复的元素 V2


    $n leq 500000,m leq 500000$的矩阵,第一行第一列是$a^b,2 leq a,b leq 500000$,如果一个数是$i^j$那他右边是$i^{j+1}$,下面是${i+1}^{j}$,问这个矩阵里有多少不同的数字。

    把数字化成“基”来统筹统计一些重复情况。意思就是:$a=prod_{i=1}^{k}p_i^{b_i}$,其中$gcd(b_1,b_2,...,b_k)=1$,那么这些$a$就可以当基,他的若干次幂在比他小的行中一定不会出现,而他的平方,三次方,这些行可能会跟他有部分重复。因此这些行单独拿出来考虑。可以看一下次数:

    $a^{1*1} a^{1*2} a^{1*3}...$

    $a^{2*1} a^{2*2} a^{2*3}...$

    $a^{3*1} a^{3*2} a^{3*3}...$

    如此,只需要在这样的矩形里的一段连续行中去重就可以了。一次考虑一个记,元素总数是$log_an*m$的,但总的元素总数仍是$n*m$的。

    可以观察到,随着基变大,这个抽象出来的矩形的连续行(叫$[L,R]$)的$L$和$R$都会变小。而这个矩形的数字范围只有$mlogn$,可以开个桶来算每次多出或损失的行。总复杂度变成这个矩形的元素总数$mlogn$。

    V3暂时不会QAQ是用容斥的观点进行搜索+剪枝的,希望能回来填坑。

     1 //#include<iostream>
     2 #include<cstring>
     3 #include<cstdio>
     4 //#include<time.h>
     5 //#include<complex>
     6 //#include<set>
     7 #include<queue>
     8 //#include<vector>
     9 #include<algorithm>
    10 #include<stdlib.h>
    11 using namespace std;
    12 
    13 #define LL long long
    14 int qread()
    15 {
    16     char c; int s=0,f=1; while ((c=getchar())<'0' || c>'9') (c=='-') && (f=-1);
    17     do s=s*10+c-'0'; while ((c=getchar())>='0' && c<='9'); return s*f;
    18 }
    19 
    20 //Pay attention to '-' , LL and double of qread!!!!
    21 
    22 int n,m,a,b;
    23 #define maxn 1000011
    24 #define maxm 10000011
    25 
    26 //int prime[maxn],lp,xx[maxn]; bool notprime[maxn];
    27 //void makeprime(int n)
    28 //{
    29 //    lp=0;
    30 //    for (int i=2;i<=n;i++)
    31 //    {
    32 //        if (!notprime[i]) {prime[++lp]=i; xx[i]=i;}
    33 //        for (int tmp,j=1;j<=lp && 1ll*i*prime[j]<=n;j++)
    34 //        {
    35 //            notprime[tmp=i*prime[j]]=1; xx[tmp]=prime[j];
    36 //            if (!(i%prime[j])) break;
    37 //        }
    38 //    }
    39 //}
    40 
    41 int cnt[maxm]; bool vis[maxn];
    42 int main()
    43 {
    44     m=qread(); n=qread(); a=qread(); b=qread(); int N=a+n-1,M=b+m-1;
    45 //    makeprime(a+n);
    46     
    47     int L=0,R=20; while ((1<<L)<a) vis[1<<L]=1,L++; while ((1<<R)>N) R--;
    48 //    cout<<L<<' '<<R<<endl;
    49     for (int i=L;i<=R;i++) vis[1<<i]=1;
    50     LL ans=0; int now=0;
    51     for (int j=L,tmp;j<=R;j++)
    52         for (int k=b;k<=M;k++)
    53         {
    54             if (cnt[tmp=j*k]==0) now++;
    55             cnt[tmp]++;
    56         }
    57     ans+=now;
    58     for (int i=3;i<=N;i++) if (!vis[i])
    59     {
    60         int nl=0,nr=0; LL tmp=1;
    61         for (;tmp<a;tmp*=i,nl++) vis[tmp]=1;
    62         nr=nl; for (;tmp<=N;tmp*=i,nr++) vis[tmp]=1; nr--;
    63 //        cout<<nl<<' '<<nr<<endl;
    64         for (int j=L-1;j>=nl;j--)
    65             for (int k=b;k<=M;k++)
    66             {
    67                 if (cnt[tmp=j*k]==0) now++;
    68                 cnt[tmp]++;
    69             }
    70         L=nl;
    71         for (int j=R;j>nr;j--)
    72             for (int k=b;k<=M;k++)
    73             {
    74                 cnt[tmp=j*k]--;
    75                 if (cnt[tmp]==0) now--;
    76             }
    77         R=nr;
    78         ans+=now;
    79     }
    80     printf("%lld
    ",ans);
    81     return 0;
    82 }
    View Code
  • 相关阅读:
    洛谷 P5057 [CQOI2006]简单题 题解
    洛谷 P3368 【模板】树状数组 2 题解
    洛谷 P3374 【模板】树状数组 1 题解
    洛谷 P2023 [AHOI2009]维护序列 题解
    洛谷 P2253 好一个一中腰鼓! 题解
    求最长不下降/上升/下降/不上升子序列
    [SQL Server]Index/deadlock
    Ubuntu 14.04下从源码安装qt4.x
    Ubuntu系统下Import cv2提示no modules ...错误
    Ubuntu 14.04下安装CUDA8.0
  • 原文地址:https://www.cnblogs.com/Blue233333/p/9164366.html
Copyright © 2020-2023  润新知