JZOJ__Day 9:【普及模拟】算法学习(sfxx)

来源:互联网 发布:java swing的gui 编辑:程序博客网 时间:2024/06/13 21:48

题目描述

自从学习了动态规划后,Famer KXP对动态规划的热爱便一发不可收拾,每天都想找点题做,一天,他找到了一道题,但是不会做,于是,他找到了你。题目如下:
给出N个无序不重复的数,再有M个询问,每次询问一个数是否在那N个数中,若在,则ans增加2^K,K为该数在原数列中的位置。
由于ans过大,所以只要求你输出ans mod 10^9+7。

输入

第一行,两个数N,M,第二行N个数,第三行M个数。

输出

输出最终答案。

样例输入

5 5
1 3 4 6 5
1 8 1 3 6

样例输出

24

数据范围限制

30% 0< N,M<100
50% 0< N,M<10000
100% 0< N,M<100000
输入的数均在2^31 以内

分析
理论时间复杂度:N*logN*logN
正解:动态规划 (骗人的)
题目背景坑人的:
30%可以暴力拿到;
50%可以用二分查找或者快速幂其一得到;

正解为二分查找+快速幂。

程序:

vara,p:array[0..100000]of int64;i:longint;n,m,ans,w,wz:int64;function f(b1,p1,k1:longint):int64;varl,t,bz:int64;i:longint;a1:array[1..32]of longint;begin    l:=0;t:=p1;    while t<>0 do    begin        inc(l);        a1[l]:=t mod 2;        t:=t div 2;    end;    bz:=1;    for i:=l downto 1 do    begin        t:=bz*bz mod k1;        if a1[i]=1 then bz:=b1 mod k1 *t mod k1 else bz:=t;    end;    exit(bz);end;procedure kp(l,r:longint);vari,j:longint;mid:int64;begin    if l>=r then exit;    i:=l;j:=r;mid:=a[(i+j) div 2];    repeat         while a[i]<mid do inc(i);         while a[j]>mid do dec(j);         if i<=j then         begin             a[0]:=a[i];a[i]:=a[j];a[j]:=a[0];             p[0]:=p[i];p[i]:=p[j];p[j]:=p[0];             inc(i);dec(j);         end;    until i>j;    kp(l,j);    kp(i,r);end;function search(k:int64):longint;varl,r,mid:int64;begin    l:=1;r:=n;    mid:=(l+r) div 2;    while (a[mid]<>k)and(l<=r) do    begin        if a[mid]>k then r:=mid-1 else l:=mid+1;        mid:=(l+r) div 2;    end;    if l>r then exit(0);    exit(mid);end;begin    assign(input,'sfxx.in');    reset(input);    assign(output,'sfxx.out');    rewrite(output);    readln(n,m);    for i:=1 to n do    begin        read(a[i]);        p[i]:=i;    end;    kp(1,n);    readln;    ans:=0;    for i:=1 to m do    begin        read(w);        wz:=search(w);        if wz>0 then ans:=ans+f(2,p[wz],1000000007);    end;    write(ans mod 1000000007);    close(input);    close(output);end.