CROC-MBTU 2012, Elimination Round (ACM-ICPC)
A....
B...
C.从后向前进行贪心,因为后一半的硬币只能是在取前一半的时候被拿掉,而对于前一半,不能确定到底是由哪种方式拿掉的...
如果n是偶数,那么拿掉n时,(n/2)*2+1也应该被拿掉,而实际上没有n+1这一堆,所以肯定不行.
C
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<cstring> 5 #define N 1010 6 using namespace std; 7 int s[N]; 8 int main(){ 9 int n; 10 while(cin>>n){ 11 for(int i=1;i<=n;i++)cin>>s[i]; 12 if(n%2==0||n==1){ 13 cout<<-1<<endl; 14 continue; 15 } 16 int ans=0; 17 for(int i=n;i>=2;i-=2){ 18 if(s[i]>0||s[i-1]>0){ 19 int maxn=max(s[i],s[i-1]); 20 s[i]-=maxn;s[i-1]-=maxn;s[i/2]-=maxn; 21 ans+=maxn; 22 } 23 } 24 if(s[1]>0){ 25 ans+=s[1]; 26 } 27 cout<<ans<<endl; 28 } 29 return 0; 30 }
D.对于第i列,从上到下进行一次或运算(-1除外)就能得出第i个数的值.
证明如下:考虑(a[i]&a[j])的每一个二进制位,如果从上到下或运算之后,这一位还是1,那么a[i]的这一位一定是1.
如果运算之后这位是0,有两种可能
第一种是a[i]这位是1,其他的均是0;
第二种是a[i]这位是0,其他的随意.
所以取0的时候不会影响到其他数进行运算,在这里我们就取成0.
按照这样的构造方式,我们可以得到其中一组解,但这不一定是唯一解
D
1 #include<iostream> 2 #include<cstring> 3 #define N 110 4 using namespace std; 5 typedef long long ll; 6 ll s[N][N]; 7 ll ans[N]; 8 int main(){ 9 int n; 10 while(cin>>n){ 11 memset(ans,0,sizeof(ans)); 12 for(int i=1;i<=n;i++) 13 for(int j=1;j<=n;j++){ 14 cin>>s[i][j]; 15 if(i!=j)ans[j]|=s[i][j]; 16 } 17 for(int i=1;i<=n;i++) 18 cout<<ans[i]<<" "; 19 cout<<endl; 20 } 21 return 0; 22 }
E.用两个变量记录一下在里面和在外面的人数即可,最后答案是所有时刻中能看到的最大值
E
1 #include<iostream> 2 #include<string> 3 #include<algorithm> 4 #include<stack> 5 using namespace std; 6 string s; 7 int main(){ 8 while(cin>>s){ 9 int t1,t2; 10 int ans=0; 11 t1=t2=0; 12 for(int i=0;i<s.size();i++){ 13 if(s[i]=='+'){ 14 if(t2>0){ 15 t2--; 16 t1++; 17 } 18 else{ 19 t1++; 20 } 21 } 22 else if(s[i]=='-'){ 23 if(t1>0){ 24 t1--; 25 t2++; 26 } 27 else t2++; 28 } 29 if(t1>ans||t2>ans)ans=max(t1,t2); 30 } 31 cout<<ans<<endl; 32 } 33 return 0; 34 }
F.模拟.用c++写应该比较恶心...别的语言貌似好写...???.待解决...
G.暴力枚举每两个点,最后统计就好,时间复杂度O(n^2)
G
1 #include<iostream> 2 #include<algorithm> 3 #include<cstring> 4 #include<string> 5 #include<map> 6 #define N 10010 7 using namespace std; 8 struct Edge{ 9 int u,v,next; 10 }edge[N]; 11 int head[N],cnt; 12 string s[N]; 13 bool v[N]; 14 map<string,int>M; 15 void add(int u,int v){ 16 edge[cnt].u=u;edge[cnt].v=v; 17 edge[cnt].next=head[u]; 18 head[u]=cnt++; 19 } 20 void init(){ 21 cnt=0; 22 memset(head,-1,sizeof(head)); 23 M.clear(); 24 } 25 int main(){ 26 int n; 27 string s1,s2; 28 while(cin>>n){ 29 init(); 30 int num=0; 31 for(int i=1;i<=n;i++){ 32 cin>>s1>>s2; 33 if(!M.count(s1)){ 34 M[s1]=++num; 35 s[num]=s1; 36 } 37 if(!M.count(s2)){ 38 M[s2]=++num; 39 s[num]=s2; 40 } 41 add(M[s1],M[s2]); 42 add(M[s2],M[s1]); 43 } 44 cout<<num<<endl; 45 for(int i=1;i<=num;i++){ 46 memset(v,0,sizeof(v)); 47 v[i]=1; 48 for(int j=head[i];j!=-1;j=edge[j].next)v[edge[j].v]=1; 49 int ans=0,maxn=-1; 50 for(int j=1;j<=num;j++){ 51 if(v[j])continue; 52 int c=0; 53 for(int k=head[j];k!=-1;k=edge[k].next) 54 if(v[edge[k].v])++c; 55 if(c>maxn){ 56 maxn=c; 57 ans=1; 58 } 59 else if(c==maxn)++ans; 60 } 61 cout<<s[i]<<" "<<ans<<endl; 62 } 63 } 64 return 0; 65 }
H.dp预处理,然后O(1)询问.
先用O(n^2)的时间判断s[i....j]是不是回文字串,然后再进行dp
dp[i][j]=dp[i][j-1]+dp[i+1][j]-dp[i+1][j-1]...
H
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #include<iostream> 5 #define N 5010 6 using namespace std; 7 char s[N]; 8 bool flag[N][N]; 9 int dp[N][N]; 10 11 void init(){ 12 memset(flag,0,sizeof(flag)); 13 memset(dp,0,sizeof(dp)); 14 s[0]='#'; 15 int n=strlen(s); 16 for(int i=1;i<=n;i++)flag[i][i]=1; 17 for(int len=2;len<=n;len++){ 18 for(int i=1;i+len-1<=n;i++){ 19 int j=i+len-1; 20 if(s[i]!=s[j])continue; 21 if(len==2||flag[i+1][j-1]) 22 flag[i][j]=1; 23 } 24 } 25 for(int len=1;len<=n;len++) 26 for(int i=1;i+len-1<=n;i++) 27 dp[i][i+len-1]=dp[i+1][i+len-1]+dp[i][i+len-2]-dp[i+1][i+len-2]+flag[i][i+len-1]; 28 } 29 30 int main(){ 31 int n; 32 while(~scanf("%s%d",s+1,&n)){ 33 init(); 34 int x,y; 35 while(n--){ 36 scanf("%d%d",&x,&y); 37 printf("%d\n",dp[x][y]); 38 } 39 } 40 return 0; 41 }