10.10 上午 考试

T1

40:

深搜

60:

m<=$10^5$时,可以dp,f[i]表示前i个星球最多的矿

f[i]=max(f[i-4],f[i-7])+val[i]

100:

打表发现只有 1 2 3 5 6 9 10 13 17 不能由4、7组合出来

所以只要把>18的距离离散成18,还像60那样dp就行了

$O(18n)$

 

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <cmath>
#include <algorithm>
#define mem(a,b) memset(a,b,sizeof(a))
#define ll long long
using namespace std;
inline int read()
{
    char q=getchar();int ans=0;
    while(q<'0'||q>'9')q=getchar();
    while(q>='0'&&q<='9'){ans=ans*10+q-'0';q=getchar();}
    return ans;
}
const int N=100006;
struct JI
{
    int pos,val;
    bool friend operator < (JI a,JI b)
    {
        return a.pos<b.pos;
    }
}ji[N];

int n,m;
int f[N*20],hh[N*20];
int ans;
int len;

void chu()
{
    sort(ji+1,ji+1+n);
    int las=0,temp;
    for(int i=1;i<=n;++i)
    {
        if(ji[i].pos-ji[i-1].pos>17)
            temp=18;
        else
            temp=ji[i].pos-ji[i-1].pos;
        hh[las+temp]+=ji[i].val;
        las+=temp;
    }
    len=las;
}

void work()
{
    int temp;
    mem(f,-60);
    f[0]=0;
    for(int i=0;i<=len;++i)
    {
        if(f[i]<-1000)
            continue;
        if(f[i+4]<f[i]+hh[i+4])
            f[i+4]=f[i]+hh[i+4];
        if(f[i+7]<f[i]+hh[i+7])
            f[i+7]=f[i]+hh[i+7];
    }
    for(int i=0;i<=len;++i)
        if(ans<f[i])
            ans=f[i];
}

int main(){

    n=read();m=read();
    for(int i=1;i<=n;++i)
        ji[i].val=read(),ji[i].pos=read();
    chu();
    work();
    cout<<ans;
}
T1

 

 

 

T2

Aavg 平均数

原式可以化简:

$$ (n+m-1)\sum_{i=1}^{n+m-1}(A_i-Aavg)^2$$

$$ ((n+m-1)\sum_{i=1}^{n+m-1}A_{i}^{2})-sum^2$$

定义f[i][j][k] 为i行j列当前sum=k时$A_{i}^2$的最小值
然后从f[i-1][j][k]和f[i][j-1][k]转移就行了

 

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <cmath>
#include <algorithm>
#define mem(a,b) memset(a,b,sizeof(a))
#define ll long long
#define dd double
using namespace std;
const int N=36;

int T;
int n,m,sum;
int a[N][N];
int f[33][33][27066];

int work()
{
    mem(f,60);
    int qqq=f[0][0][0];
    int hhh=n+m-1,temp;
    f[1][0][0]=0;
    for(int i=1;i<=n;++i)
        for(int j=1;j<=m;++j)
            for(int k=a[i][j];k<=sum;++k)
            {
                if(f[i-1][j][k-a[i][j]]!=qqq)
                {
                    temp=f[i-1][j][k-a[i][j]]+hhh*a[i][j]*a[i][j];
                    if(f[i][j][k]>temp)
                        f[i][j][k]=temp;
                }
                if(f[i][j-1][k-a[i][j]]!=qqq)
                {
                    temp=f[i][j-1][k-a[i][j]]+hhh*a[i][j]*a[i][j];
                    if(f[i][j][k]>temp)
                        f[i][j][k]=temp;
                }
            }
    int ans=0x7fffffff;
    for(int i=a[n][m];i<=sum;++i)
        if(f[n][m][i]!=qqq)
        {
            temp=f[n][m][i]-i*i;
            if(ans>temp)
                ans=temp;
        }
    return ans;
}

int main(){

    //freopen("T2.in","r",stdin);
    //freopen("T2.out","w",stdout);

    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d",&n,&m);
        sum=0;
        for(int i=1;i<=n;++i)
            for(int j=1;j<=m;++j)
            {
                scanf("%d",&a[i][j]);
                sum+=a[i][j];
            }
        printf("%d\n",work());
    }

}
T2

 

 

 

T3

M是非常小的,所以异或之后受影响的只是低位,再dfs的时候记录下来低位是那个的个数即可

(我还在想异或会不会有什么结合律之类的...)

 

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <cmath>
#include <algorithm>
#define mem(a,b) memset(a,b,sizeof(a))
#define ll long long
using namespace std;
inline int read()
{
    char q=getchar();int ans=0;
    while(q<'0'||q>'9')q=getchar();
    while(q>='0'&&q<='9'){ans=ans*10+q-'0';q=getchar();}
    return ans;
}
const int N=100006;
struct son
{
    int v,next,w;
}a1[N*2];
int first[N*2],e;
void addbian(int u,int v,int w)
{
    a1[e].v=v;
    a1[e].w=w;
    a1[e].next=first[u];
    first[u]=e++;
}

int n,M,mod;

int gget()
{
    int tt=M;
    while(tt!=(tt&(-tt)))
        tt-=(tt&(-tt));
    return tt<<1;
}

int fa[N],sh[N][21],xi[N][21];
int xihe[N],shhe[N],size[N];
int t[21];
void dfs1(int x)
{
    int temp;
    size[x]=1;
    for(int i=first[x];i!=-1;i=a1[i].next)
    {
        temp=a1[i].v;
        if(temp==fa[x])
            continue;
        fa[temp]=x;
        dfs1(temp);
        size[x]+=size[temp];
        xihe[x]+=(xihe[temp]+a1[i].w*size[temp]);

        mem(t,0);
        ++t[a1[i].w%mod];
        for(int j=0;j<mod;++j)
            t[(j+a1[i].w)%mod]+=xi[temp][j];
        for(int j=0;j<mod;++j)
            xi[x][j]+=t[j];
    }
}

int bb[21];
void dfs2(int x)
{
    int temp;
    for(int i=first[x];i!=-1;i=a1[i].next)
    {
        temp=a1[i].v;
        if(temp==fa[x])
            continue;
        shhe[temp]+=(shhe[x]+xihe[x]-(xihe[temp]+a1[i].w*size[temp])+(size[1]-size[temp])*a1[i].w);

        mem(t,0);mem(bb,0);
        ++t[a1[i].w%mod];
        for(int j=0;j<mod;++j)
            t[(j+a1[i].w)%mod]+=xi[temp][j];
        for(int j=0;j<mod;++j)
            t[j]=(xi[x][j]-t[j]+sh[x][j]);
        ++bb[a1[i].w%mod];
        for(int j=0;j<mod;++j)
            bb[(a1[i].w+j)%mod]+=t[j];
        for(int j=0;j<mod;++j)
            sh[temp][j]=bb[j];

        dfs2(temp);
    }
}

int main(){

    //freopen("T3.in","r",stdin);

    mem(first,-1);

    n=read();M=read();
    
    mod=gget();
    if(mod==0)mod=1;
    int tin1,tin2,tin3;
    for(int i=1;i<n;++i)
    {
        tin1=read();tin2=read();tin3=read();
        addbian(tin1,tin2,tin3);
        addbian(tin2,tin1,tin3);
    }
    dfs1(1);
    dfs2(1);
    int temp;
    for(int i=1;i<=n;++i)
    {
        temp=shhe[i]+xihe[i];
        for(int j=0;j<mod;++j)
            temp+=(sh[i][j]+xi[i][j])*((j^M)-j);
        printf("%d\n",temp);
    }
}
T3

 

 

 

总结:

考试的时候,一定要努力想,不要脑子抽风...

posted @ 2017-10-10 14:22  A_LEAF  阅读(137)  评论(0编辑  收藏  举报