昨天水了一下初赛题,感觉还不错。
1.Eming
直接做就可以了~~
a__b=a_b/ab;
a=ab+a__b;
a/=2;
b=ab-a;
2.Arithmetic Progression
求最长的连续等差数列~~扫一遍~~注意差为0的情况(其实没必要,但是有学弟wa了无数次)
3.A Easy Puz
有一个棋盘,最大6x6,每个元素值为0~3,不在范围内的求余,现有操作act(i,j),表示i,j这个元素的上下左右以及自己的值都减一,问把它变成全是0的棋盘最少要多少步。
枚举模拟题,这类题有个方法,不知道叫啥名字,具体如下:
显然如果暴力枚举,4^36绝对会超时(最多36个格子,每个格子有四种状态)。然后我们可以发现,如果第一行的状态已经确定,就可以计算出下一行要怎么操作(因为必须把第一行的状态变为0,而已经确定的第一行状态只能通过操作第二行才能改变它),比如第一行的状态为0 1 0,那么第二行只要对第二个格子操作1就可以了。依次做下去,会发现除了最后一行,上面都可以确定变成了0。我们只要枚举第一行的操作方案,就可以了。4^6*36的复杂度~~
int n,map[8][8],ans,am[8][8],tmap[8][8];
int mx[]={0,-1,1,0,0};
int my[]={0,0,0,-1,1};
bool istrue(int i,int j)
{
if (i>=n||i<0||j>=n||j<0) return true;
return false;
}
void add(int x,int y,int c)
{
tmap[x][y]=(((tmap[x][y]+c)%4)+4)%4;
}
void solved ()
{
memcpy(tmap,map,sizeof(tmap));
for (int i=0;i<n;i++)
{
for (int j=0;j<n;j++)
for (int k=0;k<5;k++)
{
int x=i+mx[k];
int y=j+my[k];
if (istrue(x,y)) continue;
add(x,y,-am[i][j]);
}
if (i+1<n)
for (int j=0;j<n;j++)
am[i+1][j]=tmap[i][j];
}
for (int j=0;j<n;j++)
if (tmap[n-1][j]) return ;
int sum=0;
for (int i=0;i<n;i++)
for (int j=0;j<n;j++)
sum+=am[i][j];
if (ans>sum||ans==-1) ans=sum;
}
void dfs(int row)
{
if (row==n)
{
solved();
return ;
}
for (int i=0;i<4;i++)
{
am[0][row]=i;
dfs(row+1);
}
}
4. Brackets
裸的卡特兰数,枚举第一个左括号对应的右括号位置可以推出。
5.Function
看数据就猜是找公式或者循环节,手算几个发现循环节是5~~
6.Triangle
给最多500个点的坐标,问这些个点中选三个能否组成等腰三角形。
枚举三个顶点O(n^3)的复杂度肯定超时。那么枚举一个点,求点到其余点的距离,再看是否有等距的,有则为等腰三角形(注意共线的情况,差乘解决)。复杂度为O(n^2logn),妥妥的。