2019.6.27总结

2019.6.27总结

比赛情况

100+100+100=300

Rank 1(好久没有AK了…)


T1

  • 表示这道题推了我好久…
  • 但是确实很好推,我们可以先画一个满二叉树,然后我们发现,对于每一个*操作,事实上就是把当前走到的点分成三个(即它自己以及它的两个儿子)。
  • 但是我们发现,仅仅这样做是不行的,因为之后的R操作,都会增加方案数次(原谅我语文不好,表述不清)而不是+1。而每次*操作,方案数又会变成原来的3倍。
  • 于是乎,我们得到了如下规律(刚开始ans和p都为1):
  • 1.当 P 的时候直接跳过。
  • 2.当 L 时 a n s = a n s ∗ 2 ans=ans*2 ans=ans2
  • 3.当 R 时 a n s = a n s ∗ 2 + p ans=ans*2+p ans=ans2+p
  • 4.当 * 时 a n s = a n s + a n s ∗ 2 + a n s ∗ 2 + p ans=ans+ans*2+ans*2+p ans=ans+ans2+ans2+p,并且 p = p ∗ 3 p=p*3 p=p3
  • 完美。
  • 哦,对了,还有高精度…

code

#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#define N 10005
#define ll long long
using namespace std;
//For 2000 yuan
ll lenf;
char s[N];
struct big
{
	int a[N],len,R=10000000;
	int put(int x){len=1,a[1]=x;}
	big add(big b)
	{
		big ans;
		memset(ans.a,0,sizeof ans.a),ans.len=max(len,b.len);
		for (int i=1;i<=ans.len;i++)
			ans.a[i]+=a[i]+b.a[i],ans.a[i+1]+=ans.a[i]/R,ans.a[i]%=R;
		ans.len+=(ans.a[ans.len+1]>0),len=ans.len;
		for (int i=1;i<=ans.len;i++)
			a[i]=ans.a[i];
	}
	int ch(int x)
	{
		int rest=0;
		for (int i=1;i<=len;i++)
			a[i]=a[i]*x+rest,rest=a[i]/R,a[i]%=R;
		if (rest)
			a[++len]=rest;
	}
	int output()
	{
		printf("%d",a[len]);
		for (int i=len-1;i;i--)
			printf("%07d",a[i]);
		printf("\n");
	}
}t,p;
int main()
{
	scanf("%s",s+1),lenf=strlen(s+1),t.put(1),p.put(1);
	for (int i=1;i<=lenf;i++)
	{
		if (s[i]=='P')
			continue;
		if (s[i]=='R')
			t.ch(2),t.add(p);
		if (s[i]=='L')
			t.ch(2);
		if (s[i]=='*')
			t.ch(5),t.add(p),p.ch(3);
	}
	t.output();
} 

T2

  • 最水的一题…
  • 我第一眼还以为有什么坑…
  • 由于只有两段,所以我们可以直接二分出两种猴子进场的时间差(即答案),每次O(n+m)判断即可。
  • 要记得判断一只猴子是否可以***到桃子,最后判断后面的猴子能否掰完前面猴子摘下来的桃子即可。
  • 没什么好说的。

code

#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#define N 30005
#define ll long long
using namespace std;
//For 2000 yuan
int t,n,m,l,r,mid;
struct monkey{int x,y;}a[N],b[N];
int pd(int x)
{
	int p=0,q=0;
	for (int i=1;i<=n;i++)
		if (x>=a[i].x)
			p+=1+(x-a[i].x)/a[i].y;
	for (int i=1;i<=m;i++)
		if (t-x>=b[i].x)
			q+=1+(t-x-b[i].x)/b[i].y;
	return p<=q;
}
int main()
{
	scanf("%d",&t);
	scanf("%d",&n);
	for (int i=1;i<=n;i++)
		scanf("%d%d",&a[i].x,&a[i].y);
	scanf("%d",&m);
	for (int i=1;i<=m;i++)
		scanf("%d%d",&b[i].x,&b[i].y);
	l=1,r=t;
	while (l<r)
		mid=(l+r+1)/2,(pd(mid))?l=mid:r=mid-1;
	if (pd(l+1))
		l++;
	printf("%d",l);
}

T3

  • 想了好久…(可能是太久没有做这种类型的题了吧)

  • 我们可以直接设 f [ i ] [ j ] [ k ] f[i][j][k] f[i][j][k]表示以(i,j)为正方形左上角的点,边长为 2 k 2^k 2k的正方形,最小不匹配数。

  • 然后就有一堆超级恶心的公式…

  • 不想说了,自己看吧。

  • c [ 1 ] [ 1 ] [ 0 ] = g e t ( i , j , i + E ( k − 1 ) − 1 , j + E ( k − 1 ) − 1 , 0 ) ; c[1][1][0]=get(i,j,i+E(k-1)-1,j+E(k-1)-1,0); c[1][1][0]=get(i,j,i+E(k1)1,j+E(k1)1,0);
    c [ 1 ] [ 1 ] [ 1 ] = g e t ( i , j , i + E ( k − 1 ) − 1 , j + E ( k − 1 ) − 1 , 1 ) ; c[1][1][1]=get(i,j,i+E(k-1)-1,j+E(k-1)-1,1); c[1][1][1]=get(i,j,i+E(k1)1,j+E(k1)1,1);
    c [ 1 ] [ 2 ] [ 0 ] = g e t ( i + E ( k − 1 ) , j , i + E ( k ) − 1 , j + E ( k − 1 ) − 1 , 0 ) ; c[1][2][0]=get(i+E(k-1),j,i+E(k)-1,j+E(k-1)-1,0); c[1][2][0]=get(i+E(k1),j,i+E(k)1,j+E(k1)1,0);
    c [ 1 ] [ 2 ] [ 1 ] = g e t ( i + E ( k − 1 ) , j , i + E ( k ) − 1 , j + E ( k − 1 ) − 1 , 1 ) ; c[1][2][1]=get(i+E(k-1),j,i+E(k)-1,j+E(k-1)-1,1); c[1][2][1]=get(i+E(k1),j,i+E(k)1,j+E(k1)1,1);
    c [ 2 ] [ 1 ] [ 0 ] = g e t ( i , j + E ( k − 1 ) , i + E ( k − 1 ) − 1 , j + E ( k ) − 1 , 0 ) ; c[2][1][0]=get(i,j+E(k-1),i+E(k-1)-1,j+E(k)-1,0); c[2][1][0]=get(i,j+E(k1),i+E(k1)1,j+E(k)1,0);
    c [ 2 ] [ 1 ] [ 1 ] = g e t ( i , j + E ( k − 1 ) , i + E ( k − 1 ) − 1 , j + E ( k ) − 1 , 1 ) ; c[2][1][1]=get(i,j+E(k-1),i+E(k-1)-1,j+E(k)-1,1); c[2][1][1]=get(i,j+E(k1),i+E(k1)1,j+E(k)1,1);
    c [ 2 ] [ 2 ] [ 0 ] = g e t ( i + E ( k − 1 ) , j + E ( k − 1 ) , i + E ( k ) − 1 , j + E ( k ) − 1 , 0 ) ; c[2][2][0]=get(i+E(k-1),j+E(k-1),i+E(k)-1,j+E(k)-1,0); c[2][2][0]=get(i+E(k1),j+E(k1),i+E(k)1,j+E(k)1,0);
    c [ 2 ] [ 2 ] [ 1 ] = g e t ( i + E ( k − 1 ) , j + E ( k − 1 ) , i + E ( k ) − 1 , j + E ( k ) − 1 , 1 ) ; c[2][2][1]=get(i+E(k-1),j+E(k-1),i+E(k)-1,j+E(k)-1,1); c[2][2][1]=get(i+E(k1),j+E(k1),i+E(k)1,j+E(k)1,1);
    d [ 1 ] [ 1 ] = f [ i ] [ j ] [ k − 1 ] , d [ 1 ] [ 2 ] = f [ i + E ( k − 1 ) ] [ j ] [ k − 1 ] , d [ 2 ] [ 1 ] = f [ i ] [ j + E ( k − 1 ) ] [ k − 1 ] , d [ 2 ] [ 2 ] = f [ i + E ( k − 1 ) ] [ j + E ( k − 1 ) ] [ k − 1 ] ; d[1][1]=f[i][j][k-1],d[1][2]=f[i+E(k-1)][j][k-1],d[2][1]=f[i][j+E(k-1)][k-1],d[2][2]=f[i+E(k-1)][j+E(k-1)][k-1]; d[1][1]=f[i][j][k1],d[1][2]=f[i+E(k1)][j][k1],d[2][1]=f[i][j+E(k1)][k1],d[2][2]=f[i+E(k1)][j+E(k1)][k1];
    f [ i ] [ j ] [ k ] = m i n ( f [ i ] [ j ] [ k ] , m i n ( c [ 1 ] [ 1 ] [ 0 ] + c [ 1 ] [ 2 ] [ 1 ] , c [ 1 ] [ 1 ] [ 1 ] + c [ 1 ] [ 2 ] [ 0 ] ) + d [ 2 ] [ 1 ] + d [ 2 ] [ 2 ] ) ; f[i][j][k]=min(f[i][j][k],min(c[1][1][0]+c[1][2][1],c[1][1][1]+c[1][2][0])+d[2][1]+d[2][2]); f[i][j][k]=min(f[i][j][k],min(c[1][1][0]+c[1][2][1],c[1][1][1]+c[1][2][0])+d[2][1]+d[2][2]);
    f [ i ] [ j ] [ k ] = m i n ( f [ i ] [ j ] [ k ] , m i n ( c [ 1 ] [ 1 ] [ 0 ] + c [ 2 ] [ 1 ] [ 1 ] , c [ 1 ] [ 1 ] [ 1 ] + c [ 2 ] [ 1 ] [ 0 ] ) + d [ 1 ] [ 2 ] + d [ 2 ] [ 2 ] ) ; f[i][j][k]=min(f[i][j][k],min(c[1][1][0]+c[2][1][1],c[1][1][1]+c[2][1][0])+d[1][2]+d[2][2]); f[i][j][k]=min(f[i][j][k],min(c[1][1][0]+c[2][1][1],c[1][1][1]+c[2][1][0])+d[1][2]+d[2][2]);
    f [ i ] [ j ] [ k ] = m i n ( f [ i ] [ j ] [ k ] , m i n ( c [ 1 ] [ 1 ] [ 0 ] + c [ 2 ] [ 2 ] [ 1 ] , c [ 1 ] [ 1 ] [ 1 ] + c [ 2 ] [ 2 ] [ 0 ] ) + d [ 1 ] [ 2 ] + d [ 2 ] [ 1 ] ) ; f[i][j][k]=min(f[i][j][k],min(c[1][1][0]+c[2][2][1],c[1][1][1]+c[2][2][0])+d[1][2]+d[2][1]); f[i][j][k]=min(f[i][j][k],min(c[1][1][0]+c[2][2][1],c[1][1][1]+c[2][2][0])+d[1][2]+d[2][1]);
    f [ i ] [ j ] [ k ] = m i n ( f [ i ] [ j ] [ k ] , m i n ( c [ 1 ] [ 2 ] [ 0 ] + c [ 2 ] [ 1 ] [ 1 ] , c [ 1 ] [ 2 ] [ 1 ] + c [ 2 ] [ 1 ] [ 0 ] ) + d [ 1 ] [ 1 ] + d [ 2 ] [ 2 ] ) ; f[i][j][k]=min(f[i][j][k],min(c[1][2][0]+c[2][1][1],c[1][2][1]+c[2][1][0])+d[1][1]+d[2][2]); f[i][j][k]=min(f[i][j][k],min(c[1][2][0]+c[2][1][1],c[1][2][1]+c[2][1][0])+d[1][1]+d[2][2]);
    f [ i ] [ j ] [ k ] = m i n ( f [ i ] [ j ] [ k ] , m i n ( c [ 1 ] [ 2 ] [ 0 ] + c [ 2 ] [ 2 ] [ 1 ] , c [ 1 ] [ 2 ] [ 1 ] + c [ 2 ] [ 2 ] [ 0 ] ) + d [ 1 ] [ 1 ] + d [ 2 ] [ 1 ] ) ; f[i][j][k]=min(f[i][j][k],min(c[1][2][0]+c[2][2][1],c[1][2][1]+c[2][2][0])+d[1][1]+d[2][1]); f[i][j][k]=min(f[i][j][k],min(c[1][2][0]+c[2][2][1],c[1][2][1]+c[2][2][0])+d[1][1]+d[2][1]);
    f [ i ] [ j ] [ k ] = m i n ( f [ i ] [ j ] [ k ] , m i n ( c [ 2 ] [ 1 ] [ 0 ] + c [ 2 ] [ 2 ] [ 1 ] , c [ 2 ] [ 1 ] [ 1 ] + c [ 2 ] [ 2 ] [ 0 ] ) + d [ 1 ] [ 1 ] + d [ 1 ] [ 2 ] ) ; f[i][j][k]=min(f[i][j][k],min(c[2][1][0]+c[2][2][1],c[2][1][1]+c[2][2][0])+d[1][1]+d[1][2]); f[i][j][k]=min(f[i][j][k],min(c[2][1][0]+c[2][2][1],c[2][1][1]+c[2][2][0])+d[1][1]+d[1][2]);

  • 然后…就没了。

  • 据说可以用记忆化搜索…

code

#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#define N 520
#define ll long long
#define H(x) sum[i][j][x]=sum[i-1][j][x]+sum[i][j-1][x]-sum[i-1][j-1][x]
#define E(x) (1<<(x))
using namespace std;
//For 2000 yuan
int n,f[N][N][12],sum[N][N][2],c[3][3][2],d[3][3],g;
char a[N][N];
int get(int x1,int y1,int x2,int y2,int u){return sum[x2][y2][u]-sum[x2][y1-1][u]-sum[x1-1][y2][u]+sum[x1-1][y1-1][u];}
int main()
{
	scanf("%d",&n),memset(f,63,sizeof f);
	for (int i=1;i<=n;i++)
	{
		scanf("%s",a[i]+1);
		for (int j=1;j<=n;j++)
			H(0),H(1),sum[i][j][a[i][j]-'0']++,f[i][j][0]=0;
	}
	for (int k=1;E(k)<=n;k++,g++)
		for (int i=1;i<=n;i+=E(k))
			for (int j=1;j<=n;j+=E(k))
			{
				c[1][1][0]=get(i,j,i+E(k-1)-1,j+E(k-1)-1,0);
				c[1][1][1]=get(i,j,i+E(k-1)-1,j+E(k-1)-1,1);
				c[1][2][0]=get(i+E(k-1),j,i+E(k)-1,j+E(k-1)-1,0);
				c[1][2][1]=get(i+E(k-1),j,i+E(k)-1,j+E(k-1)-1,1);
				c[2][1][0]=get(i,j+E(k-1),i+E(k-1)-1,j+E(k)-1,0);
				c[2][1][1]=get(i,j+E(k-1),i+E(k-1)-1,j+E(k)-1,1);
				c[2][2][0]=get(i+E(k-1),j+E(k-1),i+E(k)-1,j+E(k)-1,0);
				c[2][2][1]=get(i+E(k-1),j+E(k-1),i+E(k)-1,j+E(k)-1,1);
				d[1][1]=f[i][j][k-1],d[1][2]=f[i+E(k-1)][j][k-1],d[2][1]=f[i][j+E(k-1)][k-1],d[2][2]=f[i+E(k-1)][j+E(k-1)][k-1];
				f[i][j][k]=min(f[i][j][k],min(c[1][1][0]+c[1][2][1],c[1][1][1]+c[1][2][0])+d[2][1]+d[2][2]);
				f[i][j][k]=min(f[i][j][k],min(c[1][1][0]+c[2][1][1],c[1][1][1]+c[2][1][0])+d[1][2]+d[2][2]);
				f[i][j][k]=min(f[i][j][k],min(c[1][1][0]+c[2][2][1],c[1][1][1]+c[2][2][0])+d[1][2]+d[2][1]);
				f[i][j][k]=min(f[i][j][k],min(c[1][2][0]+c[2][1][1],c[1][2][1]+c[2][1][0])+d[1][1]+d[2][2]);
				f[i][j][k]=min(f[i][j][k],min(c[1][2][0]+c[2][2][1],c[1][2][1]+c[2][2][0])+d[1][1]+d[2][1]);
				f[i][j][k]=min(f[i][j][k],min(c[2][1][0]+c[2][2][1],c[2][1][1]+c[2][2][0])+d[1][1]+d[1][2]);
			}
	printf("%d",f[1][1][g]);
}

总结

今天信心题,明天加油!

(中考加油!)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值