bzoj5月月赛订正

  已完成2/9(要准备中考啊QwQ)

T1

  考虑对所有数分解质因数,其中因子>sqrt(100000)的因子最多有一个,于是我们可以暴力维护<sqrt(100000)的因子个数的前缀和。

  剩下的就是判区间里一个数出现的次数。我写了主席树。。。

  code

  

#include <bits/stdc++.h>
using namespace std;
int tot,i,j,k,n,m,x,y,t,cas,prime1[70],prime2[100001],b[100001],num1[67],num2[67],tt,c[100001],s[100001][67];
inline int read(){
    int x=0,f=1;
    char ch=getchar();
    while (ch<'0'||ch>'9'){f=ch=='-'?-f:f;ch=getchar();}
    while (ch>='0'&&ch<='9'){x=x*10+ch-48;ch=getchar();}
    return x*f;
}
inline void pre(){
    tot=0;
    for (register int i=2;i<=100000;i++)
        if (!b[i]){
            b[i]=1;prime2[i]=++tot;
            if (i<317)prime1[tot]=i,tt=tot;
            for (register int j=i;j<=100000;j+=i)b[j]=1;
        }
}
int rt[200001],l[3600001],r[3600001],size[3600001],num;
inline void Build(int &rt,int L,int R){if (!rt)rt=++num;if (L==R)return;Build(l[rt],L,L+R>>1);Build(r[rt],(L+R>>1)+1,R);}
inline void Insert(int &rt,int la,int L,int R,int v){
    if (!rt)rt=++num;
    if (L==R){size[rt]=size[la]+1;return;}
    l[rt]=l[la];r[rt]=r[la];
    int mid=L+R>>1;
    if (v<=mid){l[rt]=0;Insert(l[rt],l[la],L,mid,v);}else {r[rt]=0;Insert(r[rt],r[la],mid+1,R,v);}
}
inline int calc(int rt,int L,int R,int x){
    if (!rt)return 0;
    if (L==R)return size[rt];int mid=L+R>>1;
    if (x<=mid)return calc(l[rt],L,mid,x);else return calc(r[rt],mid+1,R,x);
}
int V[200001];
int main(){
    cas=read();pre();
    while (cas--){
        n=read();m=read();
        for (register int i=1;i<=n;i++){
            x=read();y=x;V[i]=x;
            for (register int j=1;j<=tt;j++)s[i][j]=s[i-1][j];
            for (register int j=1;j<=tt;j++){while (x%prime1[j]==0)s[i][j]++,x/=prime1[j];if (x==1)break;}
            c[i]=x;
        }
        memset(rt,0,sizeof rt);
        memset(l,0,sizeof l);
        memset(r,0,sizeof r);
        memset(size,0,sizeof size);
        num=0;Build(rt[0],1,tot);
        for (register int i=1;i<=n;i++)Insert(rt[i],rt[i-1],1,tot,prime2[c[i]]);
        while (m--){
            int L=read(),R=read();x=read();
            memset(num1,0,sizeof num1);
            memset(num2,0,sizeof num2);
            for (register int j=1;j<=tt;j++){while (x%prime1[j]==0)x/=prime1[j],num2[j]++;if (x==1)break;}
            for (register int j=1;j<=tt;j++)num1[j]=s[R][j]-s[L-1][j];
            bool bo=1;
            for (register int j=1;j<=tt;j++)if (num1[j]<num2[j]){puts("No");bo=0;break;}
            if (!bo)continue;
            if (x==1){puts("Yes");continue;}
            if (calc(rt[R],1,tot,prime2[x])-calc(rt[L-1],1,tot,prime2[x])<1)puts("No");else puts("Yes");
        }
    }
    return 0;
}
T1

T2

  考虑DP,f[i][j][x][y]表示走到i,j,并且路径上有x个没选,并在前i-1行以及第i行前j-1个里选了y个的最优值。ans显然等于max(f[n][m][i][i])0<=i<=t

  然后转移。

  f[i][j][x][y]可以直接转移到f[i][j+1][x][y]以及f[i][j+1][x+1][y](i,j+1不选)

  再考虑往下转移,(i+1,j)也可以选或不选,然后,再在(i,j+1)~(i,m)以及(i+1,1)~(i+1,j-1)中选最大的k个,转移给f[i+1][j][x+(1 or 0)][y+k]

  code

#pragma GCC optimize(2)
#include <bits/stdc++.h>
#define RI register int
using namespace std;
typedef long long ll;
int i,j,k,n,m,x,y,t,T,b[51][51][51];
ll f[51][51][21][21],a[51][51];
int read(){
    int x=0,f=1;
    char ch=getchar();
    while (ch<'0'||ch>'9'){f=ch=='-'?-f:f;ch=getchar();}
    while (ch>='0'&&ch<='9'){x=x*10+ch-48;ch=getchar();}
    return x*f;
}
inline int max(int x,int y){return x>y?x:y;}
int main(){
    T=read();
    while (T--){
        n=read();m=read();x=read();
        for (RI i=1;i<=n;i++)for (RI j=1;j<=m;j++)scanf("%lld",&a[i][j]);;
        memset(b,0,sizeof b);
        for (RI i=1;i<n;i++)
            for (RI j=1;j<=m;j++){
                for (RI k=j+1;k<=m;k++)b[i][j][++b[i][j][0]]=a[i][k];
                for (RI k=1;k<j;k++)b[i][j][++b[i][j][0]]=a[i+1][k];
                sort(b[i][j]+1,b[i][j]+1+b[i][j][0]);
            }
        memset(f,-1,sizeof f);
        f[1][1][0][0]=a[1][1];f[1][1][1][0]=0;
        for (RI i=1;i<=n;i++)
            for (RI j=1;j<=m;j++)
                for (RI k=0;k<=x;k++)
                    for (RI t=0;t<=x;t++)
                        if (f[i][j][k][t]>-1){
                            if (j<=m){
                                f[i][j+1][k][t]=max(f[i][j+1][k][t],f[i][j][k][t]+a[i][j+1]);
                                if (k<x)f[i][j+1][k+1][t]=max(f[i][j+1][k+1][t],f[i][j][k][t]);
                            }
                            if (i<n){
                                ll p=0;
                                for (RI h1=0;h1+t<=x;h1++){
                                    p+=b[i][j][b[i][j][0]-h1+1];
                                    f[i+1][j][k][t+h1]=max(f[i+1][j][k][t+h1],f[i][j][k][t]+p+a[i+1][j]);
                                    if (k<x){f[i+1][j][k+1][t+h1]=max(f[i+1][j][k+1][t+h1],f[i][j][k][t]+p);}
                                }
                            }
                        }
        ll ans=0;for (RI i=0;i<=x;i++)ans=max(ans,f[n][m][i][i]);
        printf("%lld\n",ans);
    }
    return 0;
}
T2

 

posted @ 2018-05-28 11:32  Acheing  阅读(214)  评论(0编辑  收藏  举报