训练赛20160417



5:00:00


 


 


Current Time:

2016-04-17 21:00:48

Contest Type:

Public

Start Time:

2016-04-17 12:00:00

Contest Status:

Ended

End Time:

2016-04-17 17:00:00

Manager:

​hrbustacm​


​Clone this contest​


 

 


ID



Origin



Title



​27​​ / ​​37​

Problem A

​FZU 1909​

​ An Equation ​

 

​0​​ / ​​6​

Problem B

​FZU 1910​

​ Boys and Girls ​


​3​​ / ​​6​

Problem C

​FZU 1911​

​ Construct a Matrix ​

 

​1​​ / ​​2​

Problem D

​FZU 1912​

​ Divisibility by Thirty-six ​


​24​​ / ​​30​

Problem E

​FZU 1913​

​ Easy Comparison ​


​11​​ / ​​58​

Problem F

​FZU 1914​

​ Funny Positive Sequence ​

 

 

Problem G

​FZU 1915​

​ Graph Traversal ​

 

​0​​ / ​​1​

Problem H

​FZU 1916​

​ Harmonious Substring Function ​

 

 

Problem I

​FZU 1917​

​ Interpreter ​

 

 

Problem J

​FZU 1918​

​ John’s Direction ​


​0​​ / ​​22​

Problem K

​FZU 1919​

​ K-way Merging sort ​


​16​​ / ​​32​

Problem L

​FZU 1920​

​ Left Mouse Button ​

 

 

————————————————————————————————————————————————————————————————————————————————————————————

————————————————————————————————————————————————————————————————————————————————————————————

————————————————————————————————————————————————————————————————————————————————————————————

今天比赛好算正常,不过赛后补题很是心酸,尼玛-------》》》》K题,比赛时和队友一起完成了这道题,java大数,样例都过了,不过还是没过,赛后看的题解,发现没什么区别,找了将近一个小时,没找到错误,我和队友放弃,吃饭去了,吃完回来我继续做,最后没办法了,。照着答案敲一遍,还是没对,尼玛,提交20.30次,现在都没过,,,,,,,,,,,脑袋痛

 

A题:水题,直接排序,判断第一个和最后一个之和和中间两个之和就可以了



#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
#include<math.h>
using namespace std;
int n;
int a[10];
int main(){
int cas=1;
scanf("%d",&n);
while(n--){

for(int i=0;i<4;i++)
scanf("%d",&a[i]);
sort(a,a+4);
if((a[0]+a[3])==(a[1]+a[2]))
printf("Case %d: Yes\n",cas++);
else
printf("Case %d: No\n",cas++);

}

return 0;
}


 

C题:矩阵快速幂,,,,,给出的n其实就是让你求出s(n)的值,而S(N)的值就是你需要构造的矩形的边界长度,而n的范围比较大,所以需要用矩阵快速幂,这个很容易想到,用矩阵快速幂可以很快求出

各个项。之后由于我们要的前n项之和摸m,fibonacci有一个简单的求和公式s(n)=2*f[n-1]+f[n-2]-1,所有我们就直接求出了矩形的长度,下面就是构造矩形,矩形的构造其实很容易发现边的长度

为奇数的时候是构造不了的,因为总h会有一列一行相等,但是偶数的时候,我们可以对称构造,比如当n==4

就可以对称

1  1 1 -1

1 1 -1 -1

1 0 -1 -1

0 -1 -1 -1

直接暴力输出就可以了

直接1A



#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
struct prog
{
int a[2][2] ;
void init()
{
a[0][0]=a[1][0]=a[0][1]=1;
a[1][1]=0;
}
void init1()
{
a[1][0]=a[0][1]=0;
a[0][0]= a[1][1]=1;
}
};

prog matrixmul ( prog a ,prog b , int m)
{
int i , j , k ;
prog c ;
for ( i = 0 ; i < 2; i ++ )
{
for ( j = 0 ; j < 2 ; j ++ )
{
c.a[i][j]=0;
for ( k =0 ; k < 2; k ++ )
c.a[i][j]+=(a.a[i][k]*b.a[k][j]%m) ;
c.a[i][j] %= m ;
}
}
return c ;
}
prog mul (prog s , int k , int m)
{
prog ans ;
ans.init1();

while ( k >= 1 )
{
if ( k & 1 )
ans = matrixmul ( ans , s , m) ;
k = k >> 1 ;
s = matrixmul ( s , s , m) ;
}
return ans ;
}
int ans[205][205];
int main()
{
int n, m, ca=1, t;
scanf("%d", &t);
while(t--)
{
scanf("%d%d", &n, &m);
prog s ;
s.init ( ) ;
s = mul ( s , n-1 , m) ;
int an=s.a[1][0], ann=s.a[0][0];
int sn=(2*ann+an-1)%m;
printf("Case %d: ", ca++);
if(sn==0||sn%2==1)
{
printf("No\n");
continue;
}
if(sn%2==0)
{
for(int i=1;i<=sn;i++)
{
for(int j=1;j<=(sn-i);j++)
ans[i][j]=1;
}
for(int i=1;i<=sn;i++)
{
for(int j=sn;j>(sn-i+1);j--)
ans[i][j]=-1;
}
for(int i=1;i<=sn/2;i++)
ans[i][sn-i+1]=1;
for(int i=sn/2+1;i<=sn;i++)
ans[i][sn-i+1]=0;
}
printf("Yes\n");
for(int i=1;i<=sn;i++)
{
for(int j=1;j<=sn;j++)
{
if(j!=1) printf(" ");
printf("%d", ans[i][j]);
}
printf("\n");
}
}
return 0;
}


 

E题直接排序暴力比较就可以了



#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
#include<math.h>
using namespace std;
int t;
char str1[300],str2[300];
int main(){
scanf("%d",&t);
int cas=1;
while(t--){
int n;
scanf("%d",&n);
getchar();
for(int i=0;i<n;i++){
char c;
scanf("%c",&c);
str1[i]=c;
str2[i]=c;
}
getchar();
sort(str2,str2+n);
int cnt=0;
for(int i=0;i<n;i++)
if(str1[i]!=str2[i])
cnt++;
printf("Case %d: %d\n",cas++,cnt);
}
}


 

F题,还算比较坑,我和队友之前训练赛3,4次坑在了%I64D上面,这次又坑在了这上面,不知道是foj的事还是怎么了,别的oj没遇到过这种情况

一开始我们想到的是使用树状数组,但是发现更新容易,查询费时间,,

后来想到了线性的扫一遍,我们将数列重复一遍排成2*n的长度,方便循环的查询,vis数组被标记的时候代表以当前元素为开头的序列是有负数的,不会成立,我们从后往前从第一个负数开始扫,并累加,只要

在扫到j的时候小于0,就说明以j元素开始的循环序列不成立,当大于0的时候,我们在找下一个负数,以此类推,被%I64d坑了好几次,尼玛

最后n-vis数组中被标记的就可以了



#include<stdio.h>
#include<string.h>
#include<iostream>
#include<queue>
#include<algorithm>
#include<math.h>
using namespace std;
typedef long long int LL;
LL a[2*500005];
int vis[500005];
int main()
{
int t;
scanf("%d",&t);
int ca=1;
while(t--)
{
int n;
scanf("%d", &n);
memset(vis, 0, sizeof(vis));
for(int i=0;i<n;i++)
{
scanf("%lld", &a[i]);
a[i+n]=a[i];
}
int ans=0;
for(int i=2*n-1;i>=n;i--)
{
if(i<n)
break;
if(a[i]<=0)
{
LL sum=0;
int j;
for(j=i;j>i-n;j--)
{
sum+=a[j];
if(sum<=0)
{
if(j>=n)
vis[j-n]=1;
else vis[j]=1;
}
else
{
break;
}
}
i=j;
}if(i<n)
break;
}
for(int i=0;i<n;i++)
if(vis[i]==1)
ans++;
printf("Case %d: %d\n", ca++, n-ans);
}
}


 

k题,一个简单的递归,我们将n不断的分成k堆,而在回溯的时候我们希望比较的次数最大,,,,,,,n个物品平均分成k堆,我们假设k堆数都是在进行回溯排序好了之后的元素,那么着k堆n个物品进行的

最大的比较次数就是(n-k)*(k-1)+(k-1)*k/2    ,这个公式我相信只要在纸上画一下一眼就看出来了,那么我们在dfs的时候,将他不断的分成k堆,并在回溯的时候将每一个小堆都按照上面的公式就行计算,累加就得出来了,

-------------------------------------》下面的代码我们没有通过,我们赛后找了很久都没找到bug,以后想通了再回来纠正,不过思路是对的,我们赛后看别人的代码和我们的差不多,只是递归求和的顺序不一样



import java.util.*;
import java.math.*;
public class qwerq
{

public static void main(String args[])
{
int t;
Scanner cin=new Scanner(System.in);
t=cin.nextInt();
for(int ca=1;ca<=t;ca++)
{
BigInteger n=cin.nextBigInteger(), m=cin.nextBigInteger();
System.out.printf("Case %d: ", ca);
System.out.println(abcd(n, m));
}
}
public static BigInteger abcd(BigInteger a, BigInteger b)
{
BigInteger tttttt=new BigInteger("1"), ccccccc= new BigInteger("2");
BigInteger num, div, ccc=new BigInteger("0");
div=a.divide(b);
num=a.remainder(b);
if(div.compareTo(ccc)==0)
{
BigInteger aaa=num.subtract(tttttt), bbb=num.multiply(aaa), ans=bbb.divide(ccccccc);
return ans;
}
BigInteger ans1, ans2;
ans1=abcd(div, b);

if(num.compareTo(ccc)==0)
ans2=new BigInteger("0");
else ans2=abcd(div.add(tttttt), b);

ans1=ans1.multiply(b.subtract(num));
ans2=ans2.multiply(num);

BigInteger a1=a.subtract(b), a2=a1.multiply(b.subtract(tttttt)), a3=b.multiply(b.subtract(tttttt));
a3=a3.divide(ccccccc);
BigInteger ans0=a2.add(a3);
return ans0.add(ans1.add(ans2));
}
}


 

L题,就是非常水的bfs了,直接敲了就过了,

 

我们只是需要讨论两种情况,如果没有0的话,我们只需要暴力数字的数量就可以了,要是有0的话,我们的bfs每一个含0的联通快的个数,之后加上没有被标记的数字的数量就可以了,



#include<stdio.h>
#include<string.h>
#include<iostream>
#include<queue>
#include<algorithm>
#include<math.h>
using namespace std;
int t;
char str[15][15];
bool vis[15][15];
struct node
{
int x,y;
};
struct node1
{
int x1,y1;
} que1[105];
int n;
int net[8][2]= {1,0,0,1,-1,0,0,-1,1,1,1,-1,-1,1,-1,-1};
void bfs(int xx,int yy)
{
node u,v;
u.x=xx,u.y=yy;
queue<node>q;
q.push(u);
while(!q.empty())
{
u=q.front();
q.pop();
//bool flag1=false;
for(int i=0; i<8; i++)
{
int tx=u.x+net[i][0];
int ty=u.y+net[i][1];
if((tx>=1&&tx<=n&&ty>=1&&ty<=n&&!vis[tx][ty])){
if(str[tx][ty]=='0'){
v.x=tx;
v.y=ty;
q.push(v);
}
vis[tx][ty]=true;
}
}

}
}

int main()
{
int t;
scanf("%d",&t);
int cas=1;
while(t--)
{

bool flag=false;
int sx,sy;
sx=-1,sy=-1;
int cnt=0;
int ans=0;
scanf("%d",&n);
getchar();
memset(vis,false,sizeof(vis));
for(int i=1; i<=n; i++)
{
for(int j=1; j<=n; j++)
{
scanf("%c",&str[i][j]);
if(str[i][j]=='0')
{
que1[cnt].x1=i;
que1[cnt].y1=j;
cnt++;
flag=true;
}

}
getchar();
}
if(!flag)
{
for(int i=1; i<=n; i++)
{

for(int j=1; j<=n; j++)
{
if(str[i][j]!='@')
{
ans++;
}
}

}
printf("Case %d: %d\n",cas++,ans);

}
else
{
for(int i=0; i<cnt; i++)
{
int tx=que1[i].x1;
int ty=que1[i].y1;
if(!vis[tx][ty])
{
vis[tx][ty]=true;
bfs(tx,ty);
ans++;
}

}
for(int i=1; i<=n; i++)
{

for(int j=1; j<=n; j++)
{
if(str[i][j]!='@'&&!vis[i][j])
{
ans++;
}
}

}
printf("Case %d: %d\n",cas++,ans);
}

}
return 0;
}


 

 

 

******************************************************************************************************************************

总的来说,今天最后一道java题没做出来真心很不爽,弱爆了---------------------------------------------------------------------------》》》》》》》》》》》》》》》》》

******************************************************************************************************************************