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=ans∗2。
- 3.当 R 时 a n s = a n s ∗ 2 + p ans=ans*2+p ans=ans∗2+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+ans∗2+ans∗2+p,并且 p = p ∗ 3 p=p*3 p=p∗3
- 完美。
- 哦,对了,还有高精度…
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(k−1)−1,j+E(k−1)−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(k−1)−1,j+E(k−1)−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(k−1),j,i+E(k)−1,j+E(k−1)−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(k−1),j,i+E(k)−1,j+E(k−1)−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(k−1),i+E(k−1)−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(k−1),i+E(k−1)−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(k−1),j+E(k−1),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(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 ] ; 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];
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]);
}
总结
今天信心题,明天加油!