SNOI2017题解

来源:互联网 发布:淘宝店铺运营推广方案 编辑:程序博客网 时间:2024/06/17 01:56

bzoj突然有了snoi的题,就把以前做过的拷过去好了,所以重新做一下写一个题解好了。

DAY1 T1
求一个数列:A1=1,An=Sn+nk n1018,k10

关于之前的sum的式子都可以化为一个前缀和式f[i]=2f[i1]+nk
于是我们构造一个k+2唯矩阵表示答案和i0k次幂。
然后我们用二项式定理来推算(n+1)k=kr=0Crknkr

时间复杂度:O(k3logn)

code:还是复制的

#include<bits/stdc++.h>using namespace std;#define rep(i,l,r) for(int i=l;i<=r;++i)#define rpe(i,r,l) for(int i=r;i>=l;--i)#define dyes cerr<<"yes"<<endl#define rpp(i,x,e,head) for(int i=head[x];~i;i=e[i].next)template <class Type> inline void read(Type &cur){    Type ret=0,flag=1;    char ch=getchar();    while(ch<'0'||ch>'9'){        if(ch=='-')            flag=-1;        ch=getchar();    }    while(ch>='0'&&ch<='9'){        ret=ret*10+ch-'0';        ch=getchar();    }    cur=ret*flag;}const int mod=1e9+7;typedef long long ll;ll n,k;struct matrix{    ll s[20][20];    matrix(){memset(s,0,sizeof(s));}}A,I;matrix operator * (const matrix &a,const matrix &b){    matrix c;    rep(i,0,14){        rep(j,0,14){            rep(k,0,14){                c.s[i][j]=(c.s[i][j]+a.s[i][k]*b.s[k][j]%mod+mod)%mod;            }        }    }    return c;}matrix qpow(matrix a,ll x){    matrix c=I;    while(x){        if(x&1)            c=c*a;        a=a*a;        x>>=1;    }    return c;}int main(int argc,const char * argv[]){    read(n);read(k);    A.s[0][0]=1;    rep(i,1,k){        A.s[i][0]=A.s[i][i]=1;        rep(j,0,i){            A.s[i][j]=(A.s[i-1][j]+A.s[i-1][j-1])%mod;        }    }    rep(i,0,14)        I.s[i][i]=1;    A.s[k+1][k]=1;A.s[k+1][k+1]=2;    matrix ans;    ans=qpow(A,n-1);    ll fans=0;    rep(i,0,k){        fans=((fans+ans.s[k+1][i]+ans.s[k][i])%mod+mod)%mod;    }    cout<<fans<<endl;    return 0;}

T2
离线询问:x=0get(l1,r1,x)get(l2,r2,x)
get表示区间[l,r]中x的出现次数。
q,n105
我们把这个式子拆开,
维护:(l1,r2)[x],(l1,l21)[l],(r1+1,r2)[r],(r1+1,l21)[c]
分别代表区间内数字的个数。
那么ans=(x2l2r2+c2)2

于是开始愉快的莫队吧!

拷贝代码:

//维护:(l1,r2)[z],(l1,l2-1)[l],(r1+1,r2)[r],(r1+1,l2-1)[c]//ans=(x^2-l^2-r^2)/2+(c^2)/2; #include<bits/stdc++.h>using namespace std;#define rep(i,l,r) for(int i=l;i<=r;++i)#define rpe(i,r,l) for(int i=r;i>=l;--i)#define dyes cerr<<"yes"<<endl#define rpp(i,x,e,head) for(int i=head[x];~i;i=e[i].next)template <class Type> inline void read(Type &cur){    Type ret=0,flag=1;    char ch=getchar();    while(ch<'0'||ch>'9'){        if(ch=='-')            flag=-1;        ch=getchar();    }    while(ch>='0'&&ch<='9'){        ret=ret*10+ch-'0';        ch=getchar();    }    cur=ret*flag;}typedef long long ll;const int maxn=5e4+10;inline ll read(){    ll ret=0,flag=1;char ch=getchar();    while(ch<'0'||ch>'9'){        if(ch=='-')            flag=-1;        ch=getchar();    }    while(ch>='0'&&ch<='9'){        ret=(ret<<1)+(ret<<3)+ch-'0';        ch=getchar();    }    return ret*flag;}ll belong[maxn];struct node{    int l,r;    int id;int mul;}e[maxn<<2];inline bool cmp(const node &a,const node &b){    if(belong[a.l]==belong[b.l])        return a.r<b.r;    return belong[a.l]<belong[b.l];}int cnt=0;inline void add(ll l,ll r,ll mul,ll id){    e[++cnt].l=l;e[cnt].r=r;    e[cnt].id=id;e[cnt].mul=mul;}int n,m;ll a[maxn];int num[maxn];inline ll squre(ll x){return x*x;}ll ans;inline void upd(ll p,ll delta){    ans-=squre(num[a[p]]);    num[a[p]]+=delta;    ans+=squre(num[a[p]]);}ll tans[maxn];inline void modui(){    ans=0;    for(int i=1,l=1,r=0;i<=cnt;++i){        for(;l<e[i].l;++l)            upd(l,-1);        for(;l>e[i].l;--l)            upd(l-1,1);        for(;r<e[i].r;++r)            upd(r+1,1);        for(;r>e[i].r;--r)            upd(r,-1);        tans[e[i].id]+=ans*(e[i].mul);    }}int main(int argc,const char * argv[]){    read(n);    rep(i,1,n)        read(a[i]);    read(m);    int size=sqrt(n);    rep(i,1,n)        belong[i]=(i-1)/size+1;    int l1,l2,r1,r2;    rep(i,1,m){        read(l1);read(r1);read(l2);read(r2);        add(l1,r2,1,i);        add(l1,l2-1,-1,i);        add(r1+1,r2,-1,i);        add(r1+1,l2-1,1,i);    }    sort(e+1,e+cnt+1,cmp);    modui();    for(int i=1;i<=m;i++)        cout<<tans[i]/2LL<<endl;    return 0;}