Big Event in HDU

Big Event in HDU

Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 22147    Accepted Submission(s): 7760


Problem Description
Nowadays, we all know that Computer College is the biggest department in HDU. But, maybe you don't know that Computer College had ever been split into Computer College and Software College in 2002.
The splitting is absolutely a big event in HDU! At the same time, it is a trouble thing too. All facilities must go halves. First, all facilities are assessed, and two facilities are thought to be same if they have the same value. It is assumed that there is N (0
 

Input
Input contains multiple test cases. Each test case starts with a number N (0 < N <= 50 -- the total number of different facilities). The next N lines contain an integer V (0 A test case starting with a negative integer terminates input and this test case is not to be processed.
 

Output
For each case, print one line containing two integers A and B which denote the value of Computer College and Software College will get respectively. A and B should be as equal as possible. At the same time, you should guarantee that A is not less than B.
 

Sample Input
 
   
2 10 1 20 1 3 10 1 20 2 30 1 -1
 

Sample Output
 
   
20 10 40 40
 

很有研究的一道题目
由于c[i]存放的是构成i的方法数目,因此求平均值只需要看c[sum/2]是否不等于0
再仔细考虑,sum为偶数,则平均数一定是整数,只需要看c[sum/2]?=0
sum为奇数,则一定不能平均,只需要从前面或者后面,找下一个c[i]不为0的i值,即为相对平均的数字

#include
#include
struct E {
    int value,num;
}buf[51];
//50*100*50=250000
int c1[250001],c2[250001];
int main(){
  //  freopen("in.txt","r",stdin);
    int zu;
    while(scanf("%d",&zu)!=EOF ){
        //注意这里组是整数,不能判zu!=-1,这样会tle
        if(zu<0){
            break;
        }
        //清空操作
        /*for(int i=0;i<50;i++){
            buf[i].value=0;
            buf[i].num=0;
        }*/
        memset(buf,0,sizeof(buf));
        memset(c1,0,sizeof(c1));
        memset(c2,0,sizeof(c2));
        int sum=0;
        for(int i=0;i             scanf("%d%d",&buf[i].value,&buf[i].num);
            sum+=buf[i].value*buf[i].num;
        }
        //初始化c1,c2,c1是第一个括号的系数
        //注意,一个括号的系数为最大系数,因此用乘法
        //for(int i=0;i<=buf[0].num;i+=buf[0].value){
        for(int i=0;i<=buf[0].num*buf[0].value    ;i+=buf[0].value){
            c1[i]=1;
        }
        int endj=0;
        int endk=0;
        for(int i=2;i<=zu;i++){
            endj+=buf[i-2].num*buf[i-2].value;
            // 这里必须是j++,因为jk的过程是合并括号的过程,每一项都要扫描
            //for(int j=0;j<=endj    ;j+=buf[i-2].value){
            for(int j=0;j<=endj    ;j++){
                endk=buf[i-1].num*buf[i-1].value;
                for(int k=0;k<=endk;k+=buf[i-1].value){
                    c2[j+k]+=c1[j];
                }
                
            }
            for(int j=0;j<=sum;j++){
                c1[j]=c2[j];
                c2[j]=0;
            }
        }
       
        / /c1[i]存储的数字表示构成i的方法数目,因此平均直接找c[sum/2]即可,而不是找c[i]==sum/2
        if(sum%2==0 && c1[sum/2]!=0){
            //总数是偶数,并且可平分
            printf("%d %d\n",sum/2,sum/2);
        
            
        } else{
            
            for(int i=sum/2+1;i<=sum;i++){
                if(c1[i]!=0){
                    printf("%d %d\n",i,sum-i);
                    break;
                }
            }
            
        }
        
      
        
    
    }
    return 0;
}


你可能感兴趣的:(母函数)