20190820反思

Posted starsing

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了20190820反思相关的知识,希望对你有一定的参考价值。

  这次考试考得不够好。T1开挂做的,然后T2不是很会(思路不通),T3更没有思考,还是没能深入思考

  T1:可以说这题开挂了,因为我知道小凯的疑惑,然后这题就A了;没有什么可吹的。在考试的时候这种结论一般不是很好找,一定要大胆猜想,看看转移是否可以减少。

  按照m的dp:$f[i]=max(f[i-4],f[i-7])+a[i]$60分到手。

  然后转成按照n的dp:$f[i]=max(f[j])+a[i]$(b[i]-b[j]能被4,7表示) 然后考虑如何实现后边的限制,可以先把从1到1e5的能被4,7表示的数表打出来,发现从18开始后边都能表示,那么18之前直接维护前缀最大值即可。复杂度$O(n)$

技术图片
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int N=100020;
long long f[N],maxi[N],a[N];
bool v[30];
struct nodelong long a,b;mo[N];
inline int rd()

    int s=0,w=1;
    char cc=getchar();
    for(;cc<0||cc>9;cc=getchar()) if(cc==-) w=-1;
    for(;cc>=0&&cc<=9;cc=getchar()) s=(s<<3)+(s<<1)+cc-0;
    return s*w;

bool cmp(node a,node b)

    return a.b<b.b;

int main()

    //freopen("data.in","r",stdin);
    //freopen("data.out","w",stdout);
    int n=rd(),m=rd();
    if(m<=100000)
    
        memset(f,-0x3f,sizeof(f));
        for(int i=1;i<=n;i++)
        
            int x=rd(),y=rd();
            a[y]+=x;
        
        long long  ans=0;
        f[0]=0;
        for(int i=1;i<=m;i++)
        
            if(i-4<0) f[i]=-0x7fffffff;
            else if(i-7<0) f[i]=f[i-4]+a[i];
            else f[i]=max(f[i-4],f[i-7])+a[i];
            ans=max(ans,f[i]);
        
        printf("%lld\n",ans);
    
    else
    
        v[0]=1;v[4]=1;v[7]=1;v[8]=1;v[11]=1;v[12]=1;v[14]=1;v[15]=1;v[16]=1;
        for(int i=1;i<=n;i++)
            mo[i].a=rd(),mo[i].b=rd();
        sort(mo+1,mo+n+1,cmp);
        memset(f,-0x3f,sizeof(f));
        f[0]=0;
        long long ans=0;
        for(int i=1;i<=n;i++)
        
            for(int j=i-1;j>=0;j--)
            
                if(mo[i].b-mo[j].b>17)
                
                    f[i]=max(f[i],maxi[j]+mo[i].a);
                    break;
                
                if(v[mo[i].b-mo[j].b]) f[i]=max(f[i],f[j]+mo[i].a);
            
            maxi[i]=max(maxi[i-1],f[i]);
            ans=max(ans,f[i]);
        
        printf("%lld\n",ans);
    

/*
g++ 1.cpp -o 1
./1
3 13
100 4
10 7
1 11
*/
View Code

 

  T2:差点想到正解。给n*m矩阵要求$(n+m-1)*\sum (A_i-Avag)^2$最小值。看到平方不会处理就先拆出来。

  $(n+m-1)*\sum(A_i^2-2A_i*Avag+Avag^2)$

  $\sum((n+m-1)*Ai^2-2A_i*\sum A_i+Avag*\sum A_i)$

  $(n+m-1)*\sum(A_i^2)-(\sum A_i)^2$

  然后,我就傻X的用这个柿子打搜索。。。。

  题目明确提醒,矩阵元素不大于30,以前不知道他在说啥,以后应该知道他在提示可以压进状态。

  设f[s][i][j]为到i,j的和为s的最小平方和。

  转移即可。

  

技术图片
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int S=30*920,N=40;
int f[S][N][N],a[N][N];
inline int rd()

    int s=0,w=1;
    char cc=getchar();
    for(;cc<0||cc>9;cc=getchar()) if(cc==-) w=-1;
    for(;cc>=0&&cc<=9;cc=getchar()) s=(s<<3)+(s<<1)+cc-0;
    return s*w;

int main()

    int T=rd();
    while(T--)
    
        int n=rd(),m=rd(),maxi=0;
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
                a[i][j]=rd(),maxi=max(maxi,a[i][j]);
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
                for(int s=0;s<=maxi*(n+m);s++)
                    f[s][i][j]=0x7ffffff;
        f[a[1][1]][1][1]=a[1][1]*a[1][1];
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
            
                for(int s=0;s<=maxi*(n+m);s++)
                
                    f[s+a[i+1][j]][i+1][j]=min(f[s+a[i+1][j]][i+1][j],f[s][i][j]+a[i+1][j]*a[i+1][j]);
                    f[s+a[i][j+1]][i][j+1]=min(f[s+a[i][j+1]][i][j+1],f[s][i][j]+a[i][j+1]*a[i][j+1]);
                
            
        long long ans=0x7ffffffffffffff;
        for(int s=0;s<=maxi*(n+m);s++)
        
            ans=min(1ll*ans,1ll*(n+m-1)*f[s][n][m]-s*s);
        
        printf("%lld\n",ans);
    

/*
g++ 2.cpp -o 2
./2
1
2 2
1 2
3 4
*/
View Code

 

  T3:好题,再次提醒:位运算是的运算,只和位之间有关,我们可以知道,异或不满足加法结合律,那么这个就没法树DP转移。

  那么我们可以好好想一下到底怎么处理这种东西。另外,异或的数不超过16。

  性质:由于只和位有关,我们发现,假设异或的数有k位,对于后k位相同的,异或前后变化相同,我们就可以找到后k位的数是j的路径个数,然后可以通过这个数组得到答案,这个数组满足结合律,可以树上转移,另外用最朴素的f数组存路径和。

  这两个数组既然可以树上转移,那就可以换根,最终换根算出最终答案就可以了。

  

技术图片
#include<iostream>
#include<cstdio>
using namespace std;
const int N=500020;
int fr[N],tt,fa[N],f[N],size[N],tmp[20],s[N][20],n,m,ans;
struct nodeint to,pr,w;mo[N*2];
inline int rd()

    int s=0,w=1;
    char cc=getchar();
    for(;cc<0||cc>9;cc=getchar()) if(cc==-) w=-1;
    for(;cc>=0&&cc<=9;cc=getchar()) s=(s<<3)+(s<<1)+cc-0;
    return s*w;

void add(int x,int y,int c)

    mo[++tt].to=y;mo[tt].w=c;
    mo[tt].pr=fr[x];fr[x]=tt;    

void dfs1(int x)

    size[x]=1;s[x][0]++;
    for(int i=fr[x];i;i=mo[i].pr)
    
        int to=mo[i].to;
        if(to==fa[x]) continue;
        fa[to]=x;
        dfs1(to);
        f[x]+=f[to]+size[to]*mo[i].w;
        for(int j=0;j<=15;j++)
            s[x][(j+mo[i].w)&15]+=s[to][j];
        //s[x][(mo[i].w)&15]++;
        size[x]+=size[to];
    
    /*for(int j=0;j<=15;j++)
    
        cout<<x<<" "<<j<<" "<<s[x][j]<<endl;
    */

void dfs2(int x)

    for(int i=fr[x];i;i=mo[i].pr)
    
        int to=mo[i].to;
        if(to==fa[x]) continue;
        fa[to]=x;
        f[to]=f[to]+f[x]-(f[to]+size[to]*mo[i].w)+mo[i].w*(n-size[to]);
        //cout<<to<<" "<<f[to]<<endl;
        //cout<<s[4][13]<<endl;
        for(int j=0;j<=15;j++)
        
            //cout<<to<<" "<<j<<" "<<s[x][j]<<" "<<s[to][j]<<endl;
            tmp[(mo[i].w+(j+mo[i].w)&15)&15]=s[x][(j+mo[i].w)&15]-s[to][j];
        
        
        for(int j=0;j<=15;j++)
        
            s[to][j]+=tmp[j];
            ///cout<<to<<" "<<j<<" "<<s[to][j]<<endl;
        
        dfs2(to);
    

int main()

    n=rd();m=rd();
    for(int i=1;i<n;i++)
    
        int x=rd(),y=rd(),z=rd();
        add(x,y,z);add(y,x,z);
    
    dfs1(1);
    dfs2(1);
    for(int i=1;i<=n;i++)
    
        for(int j=0;j<=15;j++)
        
            f[i]-=s[i][j]*j;
            f[i]+=s[i][j]*(j^m);
        
        printf("%d\n",f[i]-m);
    

/*
g++ 3.cpp -o 3
./3
5 3
1 2 1
1 3 2
1 4 3
2 5 4
*/
View Code

 

以上是关于20190820反思的主要内容,如果未能解决你的问题,请参考以下文章

2016.5.20反思

20165324 前四周总结反思

阶段性自我反思及学习动员----2019.07.07

暑假反思

什么是反思?

职业危机:从无到有,从弱到强;反思再反思和应对措施