The 2014 ACMICPC Asia Regional Shanghai Online
XorZip小队第一次合作,虽然结果还是有些可惜,但是状态和感觉都还不错。
【A】数论+二分(-_-///)
【B】Lucas定理+数位DP(-_-///)
【C】LCA、LCT+树链剖分
【E】DLX(-_-///)
【G】几何题,线段与椭球的交点
【H】Kuangbin说这是个简单DP(简单...0.0...)矩阵优化
【J】本福特定律(妈蛋,这是个啥?......)
【K】LCT
Contest
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
On Mars, there is programming contest, too. Each team consist of N students. The teams are given M hours to solve M programming problems. Each team can use only one computer, but they can’t cooperate to solve a problem. At the beginning of the ith hour, they will get the ith programming problem. They must choose a student to solve this problem and others go out to have a rest. The chosen student will spend an hour time to program this problem. At the end of this hour, he must submit his program. This program is then run on test data and can’t modify any more.
Now, you have to help a team to find a strategy to maximize the expected number of correctly solved problems.
For each problem, each student has a certain probability that correct solve. If the ith student solve the jth problem, the probability of correct solve is Pij .
At any time, the different between any two students’ programming time is not more than 1 hour. For example, if there are 3 students and there are 5 problems. The strategy {1,2,3,1,2}, {1,3,2,2,3} or {2,1,3,3,1} are all legal. But {1,1,3,2,3},{3,1,3,1,2} and {1,2,3,1,1} are all illegal.
You should find a strategy to maximize the expected number of correctly solved problems, if you have know all probability
The first line of each case contains two integers N ,M (1 ≤ N ≤ 10,1 ≤ M ≤ 1000),denoting the number of students and programming problem, respectively.
The next N lines, each lines contains M real numbers between 0 and 1 , the jth number in the ith line is Pij .
1 2 3 0.6 0.3 0.4 0.3 0.7 0.9
【Sample Output】
Case #1: 2.20000
【题意】
这是另一个次元的ACM比赛么...0.0...每个队伍N个人,一共M道题,每小时一题,每题限定只能有1人做题,其他人出去玩。给出每个队员对每一道题解出的概率,最后要求计算出一种方案,使得最终的出题数数学期望最大化。
1 f(i,j)表示第i题,j状态时达到的最大和,j用一个最大为2^10的数来表示每个人在当前组是否有做过题目的状态 2 则: 3 f(i,j)=max{f(i-1,j-1<<k)+a[k][i]} j&(1<<k)==(1<<k)
想明白方程之后就是分组细节上的处理了。
1 /* *********************************************** 2 MYID : Chen Fan 3 LANG : G++ 4 PROG : D1004 5 ************************************************ */ 6 7 #include <iostream> 8 #include <cstdio> 9 #include <cstring> 10 #include <algorithm> 11 12 using namespace std; 13 14 int po[]={1,2,4,8,16,32,64,128,256,512,1024,2048}; 15 double a[20][1010]; 16 bool flag[20]; 17 double f[20][2000]; 18 int n; 19 20 double doit(int l,int r,double sum) 21 { 22 memset(f,0,sizeof(f)); 23 for (int i=1;i<=r-l+1;i++) 24 for (int j=0;j<=po[n]-1;j++) 25 { 26 double temp=0; 27 for (int k=0;k<n;k++) 28 if (((1<<k)&j-(1<<k))==0) 29 if (temp<f[i-1][j-(1<<k)]+a[k+1][l+i-1]) temp=f[i-1][j-(1<<k)]+a[k+1][l+i-1]; 30 f[i][j]=temp; 31 } 32 33 return f[r-l+1][po[n]-1]; 34 } 35 36 int main() 37 { 38 int t; 39 scanf("%d",&t); 40 for (int tt=1;tt<=t;tt++) 41 { 42 int m; 43 scanf("%d%d",&n,&m); 44 for (int i=1;i<=n;i++) 45 for (int j=1;j<=m;j++) scanf("%lf",&a[i][j]); 46 47 double ans=0; 48 int t1=m/n; 49 for (int i=1;i<=t1;i++) 50 { 51 double temp=doit((i-1)*n+1,i*n,0); 52 ans+=temp; 53 } 54 double temp=doit(t1*n+1,m,0); 55 ans+=temp; 56 57 printf("Case #%d: %.5f\n",tt,ans); 58 } 59 return 0; 60 }
【启发】
有些题目可能局部是满足DP性质的,可以分解一下再做DP。
Sawtooth
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
● One straight line can divide a plane into two regions. ● Two lines can divide a plane into at most four regions. ● Three lines can divide a plane into at most seven regions. ● And so on...
Now we have some figure constructed with two parallel rays in the same direction, joined by two straight segments. It looks like a character “M”. You are given N such “M”s. What is the maximum number of regions that these “M”s can divide a plane ?
Each case contains one single non-negative integer, indicating number of “M”s. (0 ≤ N ≤ 1012)
2 1 2
【Sample Output】
Case #1: 2 Case #2: 19
【题意】
在平面上摆上M,摆上一个的时候能把平面分成2个部分,摆上2个的时候能分成19个部分,求摆上n个的时候能分成多少个部分。
【分析】
这样的题目首先能想到的肯定是通过公式推算完成,但是由两组数据还很难推出公式,于是我们艰难地画出了第三个M,最后数出来是52。
经过一番艰难地推算,算出来了公式是ans=8n^2-7n+1。
开始感觉估算出来long long是足够大的,交了一次没过,以为是公式问题,,,后来才发现10^12平方之后早就爆了64位了,于是转用大数。
比赛时用了JAVA,TLE,然后之前又没有自己准备C的大数模板,悲剧收场...
【JAVA】
队友整理了个好用的JAVA模板,这玩意以前还不怎么会,经过这次之后应该是没问题了。
1 /* *********************************************** 2 MYID : Chen Fan 3 LANG : JAVA 4 PROG : HDU5047 5 ************************************************ */ 6 7 import java.io.*; 8 import java.math.BigInteger; 9 import java.util.*; 10 11 public class Main 12 { 13 static PrintWriter out=new PrintWriter(new BufferedWriter( 14 new OutputStreamWriter(System.out))); 15 16 public static void main(String[] args) throws IOException 17 { 18 Scan scan=new Scan(); 19 20 int t=scan.nextInt(); 21 for (int tt=1;tt<=t;tt++) 22 { 23 String s=scan.next(); 24 BigInteger a=new BigInteger(s); 25 a=a.multiply(BigInteger.valueOf(8)).multiply(a).subtract(a.multiply(BigInteger.valueOf(7))).add(BigInteger.valueOf(1)); 26 out.printf("Case #%d: ",tt); 27 out.println(a); 28 } 29 30 out.flush(); 31 } 32 } 33 34 class Scan 35 { 36 BufferedReader buffer; 37 StringTokenizer tok; 38 39 Scan() 40 { 41 buffer=new BufferedReader(new InputStreamReader(System.in)); 42 } 43 44 boolean hasNext() 45 { 46 while (tok==null||!tok.hasMoreElements()) 47 { 48 try 49 { 50 tok=new StringTokenizer(buffer.readLine()); 51 } catch (Exception e) 52 { 53 return false; 54 } 55 } 56 return true; 57 } 58 59 String next() 60 { 61 if (hasNext()) return tok.nextToken(); 62 return null; 63 } 64 65 int nextInt() 66 { 67 return Integer.parseInt(next()); 68 } 69 }
【不用JAVA】
其实最终的结果没有超出long long太多,当时比赛的时候脑子没转过来,用两个long long的变量把结果分成两部分完全就能存下来了-_-////哭死,这个思路就是简化版的大数操作。
Divided Land
Time Limit: 8000/4000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
Each case contains two binary number represents the length L and the width W of given land. (0 < L, W ≤ 21000)
3 10 100 100 110 10010 1100
【Sample Output】
Case #1: 10 Case #2: 10 Case #3: 110
【题意】
给出一块平面,要求使用一些正方形去摆满,求最大正方形的边长。
【分析】
首先要想到正方形分矩形的最大边长是其长和宽的最大公约数。
然后就是计算二进制(大数)的最大公约数的问题了。
很不好意思的是,JAVA中也是直接有模板可以套用的,而且借由快速的输入输出模板,题目变得so easy了。
1 /* *********************************************** 2 MYID : Chen Fan 3 LANG : JAVA 4 PROG : HDU5050 5 ************************************************ */ 6 7 import java.io.*; 8 import java.math.BigInteger; 9 import java.util.*; 10 11 public class Main 12 { 13 static PrintWriter out=new PrintWriter(new BufferedWriter( 14 new OutputStreamWriter(System.out))); 15 16 public static void main(String[] args) throws IOException 17 { 18 Scan scan=new Scan(); 19 20 int t=scan.nextInt(); 21 22 for (int tt=1;tt<=t;tt++) 23 { 24 String s=scan.next(); 25 BigInteger a=new BigInteger(s,2); 26 s=scan.next(); 27 BigInteger b=new BigInteger(s,2); 28 out.printf("Case #%d: ",tt); 29 out.println(a.gcd(b).toString(2)); 30 } 31 32 out.flush(); 33 } 34 } 35 36 class Scan 37 { 38 39 BufferedReader buffer; 40 StringTokenizer tok; 41 42 Scan() 43 { 44 buffer=new BufferedReader(new InputStreamReader(System.in)); 45 } 46 47 boolean hasNext() 48 { 49 while (tok==null||!tok.hasMoreElements()) 50 { 51 try 52 { 53 tok=new StringTokenizer(buffer.readLine()); 54 } catch (Exception e) 55 { 56 return false; 57 } 58 } 59 return true; 60 } 61 62 String next() 63 { 64 if (hasNext()) return tok.nextToken(); 65 return null; 66 } 67 int nextInt() 68 { 69 return Integer.parseInt(next()); 70 } 71 }
the Sum of Cube
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
2 1 3 2 5
【Sample Output】
Case #1: 36 Case #2: 224
【分析】