16 hrbust邀请赛D、F题解

来源:互联网 发布:中国网络电视台体育台 编辑:程序博客网 时间:2024/05/16 17:11

周末打了个kuangbin聚聚出的网络邀请赛,水了7个题,旗神来写了一个,rk16滚粗。

其实说是写了7个题,但是5个sb题,1个模板题,1个找规律题,后面的题都没怎么看,据说有一个网络流还有两个神题?所以我这这场干了啥。。。

D是给了1e5个1e5以内的数,然后给1e5个询问k,k是2e5,问有多少个pair(i,j),满足ai+aj小于k。
一边吃饭一边看了约20min,发现就是个裸的FFT|NTT,卷积一下求个前缀和,然后把自己匹配的减掉就好了。于是愉快地拍(copy&paste)了一个强无敌的NTT板子,xjb调调就过了。

板子如下:

#include<cstdio>#include<cstring>#include<algorithm>using namespace std;#define MAXN 262144const long long P=50000000001507329LL; // 190734863287 * 2 ^ 18 + 1//const int P=1004535809; // 479 * 2 ^ 21 + 1//const int P=998244353; // 119 * 2 ^ 23 + 1const int G=3;long long mul(long long x,long long y){    return (x*y-(long long)(x/(long double)P*y+1e-3)*P+P)%P;}long long qpow(long long x,long long k,long long p){    long long ret=1;    while(k)    {        if(k&1) ret=mul(ret,x);        k>>=1;        x=mul(x,x);    }    return ret;}long long wn[25];void getwn(){    for(int i=1; i<=18; ++i)    {        int t=1<<i;        wn[i]=qpow(G,(P-1)/t,P);    }}int len;void NTT(long long y[],int op){    for(int i=1,j=len>>1,k; i<len-1; ++i)    {        if(i<j) swap(y[i],y[j]);        k=len>>1;        while(j>=k)        {            j-=k;            k>>=1;        }        if(j<k) j+=k;    }    int id=0;    for(int h=2; h<=len; h<<=1)    {        ++id;        for(int i=0; i<len; i+=h)        {            long long w=1;            for(int j=i; j<i+(h>>1); ++j)            {                long long u=y[j],t=mul(y[j+h/2],w);                y[j]=u+t;                if(y[j]>=P) y[j]-=P;                y[j+h/2]=u-t+P;                if(y[j+h/2]>=P) y[j+h/2]-=P;                w=mul(w,wn[id]);            }        }    }    if(op==-1)    {        for(int i=1; i<len/2; ++i) swap(y[i],y[len-i]);        long long inv=qpow(len,P-2,P);        for(int i=0; i<len; ++i) y[i]=mul(y[i],inv);    }}void Convolution(long long A[],long long B[],int len1,int len2){    int n=max(len1,len2);    for(len=1; len<(n<<1); len<<=1);    for(int i=len1; i<len; ++i)    {        A[i]=0;    }    for (int i=len2;i<len;i++)    {        B[i]=0;    }    NTT(A,1);    NTT(B,1);    for(int i=0; i<len; ++i)    {        A[i]=mul(A[i],B[i]);    }    NTT(A,-1);}long long A[MAXN],B[MAXN];long long sum[MAXN<<1];long long sum2[MAXN];int main(){    getwn();    int t;    scanf("%d", &t);    while(t--)    {        memset(A, 0, sizeof(A));        memset(B, 0, sizeof(B));        int n, m;        scanf("%d%d", &n, &m);        int M=0;        for(int i=1;i<=n;i++){            int tmp;            scanf("%d", &tmp);            A[tmp]++;            B[tmp]++;            M=max(M, tmp);        }        sum2[0]=B[0];        for(int i=1;i<=M+1;i++)sum2[i]=sum2[i-1]+B[i];        Convolution(A,B,M+1,M+1);        sum[0]=A[0];        for(int i=1;i<=2*M+2;i++)sum[i]=sum[i-1]+A[i];        for(int i=1;i<=m;i++){            int k;            scanf("%d", &k);            if(k>2*M+1)k=2*M+1;            printf("%lld\n", (sum[k-1]-sum2[(k-1)/2])/2);        }    }    return 0;}

然后F在旗神的打表下,发现fib数列偏移值是6为循环节,大概是0 -1 0 1 0 1,然后发现转移矩阵搞个循环队列就ok了,于是结束前30min水过,挂机结束。

水过代码:

#include <cstdio>#include <cstring>using namespace std;typedef long long ll;const int mod=1e9+7;struct mat{    ll a[8][8];};mat mult(mat a, mat b){    mat ans;    for(int i=0;i<8;i++)        for(int j=0;j<8;j++){            ans.a[i][j]=0;            for(int k=0;k<8;k++)                ans.a[i][j]=(ans.a[i][j]+a.a[i][k]*b.a[k][j])%mod;        }    return ans;}mat power(ll n){    mat ans;    for(int i=0;i<8;i++)        for(int j=0;j<8;j++)ans.a[i][j]=(i==j);    mat base;    memset(base.a, 0, sizeof(base.a));    base.a[0][0]=base.a [0][1]=base.a[0][2]=base.a[1][0]=base.a[2][3]=base.a[3][4]=base.a[4][5]=base.a[5][6]=base.a[6][7]=base.a[7][2]=1;    while(n){        if(n&1){            ans=mult(ans, base);        }        base=mult(base, base);        n>>=1;    }    return ans;}int main(){    ll n;    while(~scanf("%lld", &n)){        if(!n){            printf("7\n");            continue;        }        mat ans=power(n-1);        ll aa=(ans.a[0][0]*11+ans.a[0][1]*7-ans.a[0][3]+ans.a[0][5]+ans.a[0][7]+mod)%mod;        printf("%lld\n", aa);    }}

挂机之后就愉快地玩耍去了。

0 0
原创粉丝点击