【比赛报告】2018.10.16校赛[2015-10-04 NOIP模拟赛 by hzwer] NOIP练习赛卷十五

比赛时间:2018.10.16 选手:lrllrl 得分:70+0+10=80 用时:2小时


在这里插入图片描述
在这里插入图片描述
(让我想起了NOIPDAY1T1)
d p [ i ] dp[i] dp[i] 表示走到 i i i 位置采到的最大数量,然后直接转移就好了。唯一的问题是 i i i 的范围可以达到 1 e 9 1e9 1e9。不过我们知道,由于 4 4 4 7 7 7 互质,不能用形如 4 x + 7 y 4x+7y 4x+7y 表示的最大整数为 4 × 7 − 4 − 7 = 17 4\times 7-4-7=17 4×747=17,所以我们把所有差值大于 17 17 17 的看成 18 18 18 就行了。

#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int N=1e5+10;
int n,m,dp[N*20],a[N],ans;
namespace pts60{
	void solve()
	{
		for(int i=1;i<=n;i++)
		{
			int x,y;
			scanf("%d%d",&x,&y);
			a[y]=x;
		}
		for(int i=0;i<=m;i++)
		    dp[i+4]=max(dp[i+4],dp[i]+a[i+4]),dp[i+7]=max(dp[i+7],dp[i]+a[i+7]),ans=max(ans,dp[i]);
		printf("%d\n",ans);
	}
}
struct node{
	int a,b;
	bool operator <(const node&rhs)const{
	return b<rhs.b;}
}p[N*20];
int b[N*20];
int main()
{
	//freopen("mining.in","r",stdin);
	//freopen("mining.out","w",stdout);
	memset(dp,-1,sizeof(dp));dp[0]=0;
    scanf("%d%d",&n,&m);
    //if(m<=100000)pts60::solve();
    for(int i=1;i<=n;i++)
        scanf("%d%d",&p[i].a,&p[i].b);
    sort(p+1,p+n+1);
    int maxn=0;
    for(int i=1;i<=n;i++)
    	maxn+=(p[i].b-p[i-1].b<=17)?p[i].b-p[i-1].b:18,b[maxn]+=p[i].a;
	for(int i=0;i<=maxn;i++)
	    if(dp[i]>=0)dp[i+4]=max(dp[i+4],dp[i]+b[i+4]),dp[i+7]=max(dp[i+7],dp[i]+b[i+7]),ans=max(ans,dp[i]);
	printf("%d\n",ans);
	return 0;
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

#include<cstdio>
#include<algorithm>
using namespace std;
const int INF=0x3f3f3f3f;
int ans,t,n,m,a[35][35],f[1805][35][35],N;
//f[s][x][y]表示到(x,y)和为s的最小∑ai^2 
int main()
{
	//freopen("in.txt","r",stdin);
	scanf("%d",&t);
	while(t--)
	{
		scanf("%d%d",&n,&m);ans=INF;N=(n+m)*30;
		for(int i=1;i<=n;i++)
		    for(int j=1;j<=m;j++)
		        scanf("%d",&a[i][j]);
		for(int i=1;i<=n;i++)
		    for(int j=1;j<=m;j++)
		        for(int k=0;k<=N;k++)
		            f[k][i][j]=1000000;
		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 k=0;k<=N;k++)
		            if(f[k][i][j]!=1000000)
		            {
		            	int x=i+1,y=j,v=a[x][y];
		            	f[k+v][x][y]=min(f[k+v][x][y],f[k][i][j]+v*v);
		            	x=i,y=j+1,v=a[x][y];
		            	f[k+v][x][y]=min(f[k+v][x][y],f[k][i][j]+v*v);
					}
		for(int i=1;i<=N;i++)
		    if(f[i][n][m]!=1000000)
		        ans=min(ans,(n+m-1)*f[i][n][m]-i*i);
		printf("%d\n",ans);
	}
	return 0;
}

在这里插入图片描述
在这里插入图片描述


在这里插入图片描述

#include<cstdio>
const int N=1e5+1000,M=16;
int n,m,hd[N],tot,f[N][M],F[N],g[M];
//f[i][j]表示走到i节点时j(0~15)的个数 
//F[i]表示i点出去的所有路径中不会被异或掉的部分 
struct Edge{
	int v,w,nx;
}e[N<<1];
void add(int u,int v,int w)
{
	e[++tot].v=v;
	e[tot].w=w;
	e[tot].nx=hd[u];
	hd[u]=tot;
}
void dfs1(int u,int fa)//求v的子树的边权和 
{
	for(int i=hd[u];i;i=e[i].nx)
	{
		int v=e[i].v;
		if(v==fa)continue;
		dfs1(v,u);
		F[u]+=F[v]+e[i].w/M;//大于15的部分额外记一个值 
		f[u][e[i].w%M]++;
		for(int j=0;j<M;j++)
		{
			int k=j+e[i].w;
			F[u]+=k/M*f[v][j];
			f[u][k%M]+=f[v][j];
		}
	}
}
void dfs2(int u,int fa)//求v的子树以外的边权和 
{
	for(int i=hd[u];i;i=e[i].nx)
	{
		int v=e[i].v;if(v==fa)continue;
		int tmp=F[u]-F[v]-e[i].w/M;
		for(int j=0;j<M;j++)
		{
			int k=j+e[i].w;
			tmp-=k/M*f[v][j];
			g[k%M]=f[u][k%M]-f[v][j];
		}
		g[e[i].w%M]--;
		F[v]+=tmp+e[i].w/M;
		f[v][e[i].w%M]++;
		for(int j=0;j<M;j++)
		{
			int k=j+e[i].w;
			F[v]+=k/M*g[j];
			f[v][k%M]+=g[j];
		}
		dfs2(v,u);
	}
}
int main()
{
	//freopen("in.txt","r",stdin);
    scanf("%d%d",&n,&m);
    int u,v,w;
    for(int i=1;i<n;i++)
        scanf("%d%d%d",&u,&v,&w),add(u,v,w),add(v,u,w);
    dfs1(1,0);dfs2(1,0);
    for(int i=1;i<=n;i++)
    {
    	int ans=F[i]<<4;//复原那些不会被异或的部分 
    	for(int j=0;j<M;j++)
    	    ans+=(j^m)*f[i][j];
    	printf("%d\n",ans);
	}
	return 0;
} 

赛后总结

打的很不好。预计分数是100+30+30=160,T1在临提交时发现数组大小开小了,修改时漏掉dp数组,丢30分。T2爆搜可以过30分的,但是只有0分。T3暴力只打了10分。
问题:1.在考虑一个数能不能用4和7的组合表示出来的时候,没有第一时间想到去年DAY1T1小凯的疑惑那题的结论,非常不应该。
2.DP数组没有去修改。
3.暴力水平很低,爆搜完全没得分。
反思

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值