回 帖 发 新 帖 刷新版面

主题:第70次编程比赛题目

[size=3]上次比赛冠军得主因为长时间没有再在此发帖子,也联系不到
正好偶有题目,先抢占个位置了。。。

本次比赛题目如下:

[color=Blue]题目描述:[/color]
有n个正整数(4<=n<=13),在这n个正整数之间插入四则运算符,
使得结果恰好等于一个给定的整数值,注意这n个整数的先后顺序不能改变,
不插入运算符的地方的数字直接连起来成一个新数,
如1 2之间不插入运算符则为12,1 2 3之间的话则为整数123
如:1*23-4=19  12+3+4=19

[color=Blue]输入:[/color]
你的程序只需处理一组测试数据,每组第一行1个正整数n
接下来一行为n个小于20的正整数,这n个数和结果连起来总长度小于15位
第三行为要计算出的结果k(-10000<k<10000)

[color=Blue]输出:[/color]
输出1行1个整数,表示解的个数

[color=Blue]样例输入:[/color]
4
1 2 3 4
2

[color=Blue]样例输出:[/color]
2

[color=Blue]其它信息:[/color]
对于样例,只有
1+2+3-4 = 2
1*2*3-4 = 2
两组解
注意 -1+2-3+4=2 这组不合法,只能为四则运算符,不能作为正负号
[color=Red]你需要考虑运算优先级[/color]
题目来源:yzfy无聊改编


比赛结束时间:8月18日 23:00
比赛代码提交方式:直接回复本帖子,回复将隐藏
主要评比内容:代码时间效率
比赛注意事项:必须严格按照要求进行输入输出,不要输出多余的内容
其它:本题提供在线测试,链接[url]http://yzfy.org/dis/listpost.php?tid=897[/url]
如有疑问,请到[url]http://bbs.pfan.cn/post-282271.html[/url]提出
[/size]

回复列表 (共34个回复)

21 楼


[code=c]
/*********************************************************************************
*             Written by jowenshaw, 16 Oct 2008.
*                       Compiled by
*             DEV-C++ 4.9.9.9.2  && TC++ 3.0 && VC++ 6.0
**********************************************************************************
*                       说   明
*
*   1.  对测试数据规模过大,例如(13个9)=9的运算结果均达到百万以上(我的结果为1551854)。
*   所需时间需要4-6分钟。请不要过早CTRL+C或使用其它强制手段退出。建议先测试小规模数据。
*   
*   2.  若无任何结果输出,请检查输入数据是否合乎要求,参看以下控制输入参数注释。
*
*   3.  本程序采用双数组法避免浮点运算,因为浮点运算依赖于机器精度。一般检验程序的正确
*   性方法是让程序在不同编译器或机器上运行,看结果是否一致(输入数据规模大一些)。
*
*   4.  本程序想尽量减少与题目给定条件的特殊依赖性,使之更具广泛性(采用全局变量
*   传递信息的方法有待改进)。
************************************************************************************/

#include<stdio.h>
#include<stdlib.h> 

long cal(long **num,int len,long k,int lev);
long max1=0L,max2=0L,max_k=0L;
int main()
{

   /***************************************************************************************
    *控制输入参数,可在此修改相应参数,max1,max2表示分子分母的最大可能取值,
    *采用全局变量以方便子程序共享。输入m(no_min<=m<=no_max)个不大于num_max的正整数
    *(第一项可为零以完成取相反数运算),使得在相邻数之间加上运算符(连接,加,减,乘,除)
    *后表达式的值为k(-k_max<=k<=k_max). 其中m个数据和结果k的数字长度之和
    *(即包含数字的个数)不大于len_max.
    ***************************************************************************************/
    ////////////////////////////////////////////////////////////////////////////////////////
    int no_min=2;
    int no_max=13;     
    int k_max=9999;
    int len_max=14; //(<=18)太长可能产生越界
    long num_max=999999999L;
    /////////////////////////////////////////////////////////////////////////////////////////

     int n;
     long *num;
     long k;     
     long res=0L;  
     long *num0;
     long *num1[2];
     int i;   
     long temp;     
     int len,len_k;

     //input from the keyboard, exit if illegal!
     if(!scanf("%d",&n)) exit(-1);  
     if(n<no_min||n>no_max) exit(-1);  
     num=(long*)malloc(n*sizeof(long));
     for(i=0;i<n;i++)
     {         
        if(!scanf("%ld",&num[i]))  exit(-1);
        if(i==0)
        {
            if(num[i]<0||num[i]>num_max) exit(-1);
        }
        else
        {
            if(num[i]<1||num[i]>num_max) exit(-1);
        }
     }
     if(!scanf("%ld",&k)) exit(-1);   
     if(k<-k_max||k>k_max) exit(-1);    
     len_k=0;      
     temp=k;
     while(temp!=0)
     {
         temp/=10;
         len_k++;
     }
     len=0;
     for(i=0;i<n;i++)
     {
         temp=num[i];
         while(temp!=0)
         {
             temp/=10;
             len++;
         }
     }
     if(len_k+len>len_max) exit(-1);  

     //calulate max1,max2,max_k        
      len=len_max/2;
      max1=9;
      for(i=1;i<len;i++)
      {          
          max1=max1*10+9;
      }                 
      len=(len_max+1-2*len_k)/2;
      max2=9;
      for(i=1;i<len;i++)
      {
          max2=max2*10+9;
      }
      len=(len_max-1)/2;
      max_k=9;
      for(i=1;i<len;i++)
      {          
          max_k=max_k*10+9;
      }     
  
     num0=(long*)malloc(n*sizeof(long));
     for(i=0;i<n;i++)
     {
         num0[i]=1;
     }
     num1[0]=num;
     num1[1]=num0;
     res=cal(num1,n,k,0);
     printf("%ld\n",res);  

     free(num); 
     free(num0);     
     //system("PAUSE");//use this only when compiled by DEV-C++ to see the results.
     return 0;
}
[/code]

22 楼


[code=c]
/*********************************************************************************
*             Written by jowenshaw, 16 Oct 2008.
*                       Compiled by
*             DEV-C++ 4.9.9.9.2  && TC++ 3.0 && VC++ 6.0
**********************************************************************************
/*******************************************************************************************
//看懂本程序的关键。
//lev=0,1,2,k0(k=1,2,...,len-1),h1(h=1,2,...,len-1)。
//lev%10==0表示第lev/10个元素之后可进行一切运算(包括连接运算),而之前不包括连接运算。
//lev%10==1表示第lev/10个元素之后可进行加减乘除运算,而之前只能进行加减运算。
//lev%10==2表示只能进行加减运算。数值0只参与加减运算。
//为了避免除法产生浮点数(机器因为精度容易导致错误),采用双数组法。即分子分母各占一个数组
********************************************************************************************/
long cal(long **num,int len,long k,int lev)
{
      long count=0;   
      long *num1;//分子
      long *num2;//分母
      long *num3[2];  
      long base;    
      int  offset;
      int  i,j;//loop
      long t1,t2,t,temp1,temp2,temp;//temp
         
      if(len==2)
      {               
           switch(lev)
           {   //don't use break
               case 0:
                    if(num[0][0]>0&&num[0][1]>0)
                    {    
                        temp=num[0][1];
                        base=1;
                        while(temp!=0)
                        {
                            temp/=10;
                            base*=10;
                        }            
                        if(num[0][0]<=k/base&&num[0][0]*base+num[0][1]==k) 
                        {
                            count++;                                             
                        }                        
                    }  
[/code]

23 楼


[code=c]
/*********************************************************************************
*             Written by jowenshaw, 16 Oct 2008.
*                       Compiled by
*             DEV-C++ 4.9.9.9.2  && TC++ 3.0 && VC++ 6.0
**********************************************************************************
              case 1:
                    if(num[0][0]!=0&&num[0][1]!=0)
                    {                    
                        if(num[0][1]%num[1][0]==0
                            &&k%num[0][0]==0
                            &&num[0][1]/num[1][0]==k/num[0][0])
                        {
                             count++;                             
                        }                    
                        if(num[1][0]==1
                            &&num[0][0]%num[0][1]==0
                            &&num[0][0]/num[0][1]==k)
                        {
                             count++;                                            
                        }
                    }
              case 2:
                    if(num[1][0]==num[1][1]
                        &&(num[0][0]+num[0][1])%num[1][0]==0
                        &&(num[0][0]+num[0][1])/num[1][0]==k)
                    {
                         count++;                             
                    }
                    if(num[1][0]==num[1][1]
                        &&(num[0][0]-num[0][1])%num[1][0]==0
                        &&(num[0][0]-num[0][1])/num[1][0]==k)
                    {                    
                         count++;                            
                    }                       
           }
           return count;   
      }         
      if(lev%10!=2)  
      {
           count+=cal(num,len,k,lev%10+1);                                
      }           

      num1=(long*)malloc((len-1)*sizeof(long));  
      num2=(long*)malloc((len-1)*sizeof(long));       
      num3[0]=num1;
      num3[1]=num2;
        
      for(i=0;i<len-1;i++)
      {
         num2[i]=1;
      }
[/code]

24 楼


[code=c]
/*********************************************************************************
*             Written by jowenshaw, 16 Oct 2008.
*                       Compiled by
*             DEV-C++ 4.9.9.9.2  && TC++ 3.0 && VC++ 6.0
**********************************************************************************
          //calculate num[i] and num[i+1] first and recursive. 
      //case 2 is an exception, always calculate num[0] and num[1] first.
      offset=lev/10==0?0:lev/10;
      switch(lev%10)
      {
           case 0:                     
                 for(i=offset;i<len-1;i++)
                 {                       
                     //concat, only positive ones can do this.
                     if(num[0][i]>0&&num[0][i+1]>0)  
                     {                    
                         temp=num[0][i+1];
                          base=1;
                          while(temp!=0)
                         {
                             temp/=10;
                             base*=10;
                         }    
                         if(num[0][i]<=max1/base)
                         {
                             num1[i]=num[0][i]*base+num[0][i+1];                         
                             for(j=0;j<i;j++)
                             {
                                 num1[j]=num[0][j];    
                             }
                             for(j=i+2;j<len;j++)
                             {
                                 num1[j-1]=num[0][j];
                             }  
                             if(i==len-2)
                                 lev=1;
                             else
                                 lev=i*10;     
                             
                             count+=cal(num3,len-1,k,lev);          
                         
                         }
                     }
                 }                   
                 break;   
[/code]

25 楼


[code=c]
/*********************************************************************************
*             Written by jowenshaw, 16 Oct 2008.
*                       Compiled by
*             DEV-C++ 4.9.9.9.2  && TC++ 3.0 && VC++ 6.0
**********************************************************************************
            case 1:                                        
                 for(i=offset;i<len-1;i++)
                 {                         
                       for(j=0;j<i;j++)
                       {
                           num1[j]=num[0][j];  
                           num2[j]=num[1][j];
                       }
                       for(j=i+2;j<len;j++)
                       {
                           num1[j-1]=num[0][j];
                           num2[j-1]=num[1][j];
                       }                   
                       if(i==len-2)
                             lev=2;
                       else
                             lev=i*10+1;                    
                           
                       if(num[0][i]>0&&num[0][i+1]>0)
                       {                      
                           if(num[0][i]<=max1/num[0][i+1])
                           {
                               //multiply
                               num1[i]=num[0][i]*num[0][i+1];
                               num2[i]=num[1][i];                   
                               //约分
                               if(num2[i]!=1)
                               {
                                   temp1=num1[i];
                                   temp2=num2[i];         
                                   while(temp2!=0)
                                   {            
                                       temp=temp1%temp2;
                                       temp1=temp2;
                                       temp2=temp;
                                   }                 
                                   num1[i]/=temp1;    
                                   num2[i]/=temp1;    
                               }
                               count+=cal(num3,len-1,k,lev);                                 
                           }
[/code]

26 楼


[code=c]
/*********************************************************************************
*             Written by jowenshaw, 16 Oct 2008.
*                       Compiled by
*             DEV-C++ 4.9.9.9.2  && TC++ 3.0 && VC++ 6.0
**********************************************************************************
//divide
                           if(num[1][i]<=max2/num[0][i+1])
                           {
                               num1[i]=num[0][i];
                               num2[i]=num[1][i]*num[0][i+1];                   
                               //约分
                               if(num2[i]!=1)
                               {
                                   temp1=num1[i];
                                   temp2=num2[i];         
                                   while(temp2!=0)
                                   {            
                                       temp=temp1%temp2;
                                       temp1=temp2;
                                       temp2=temp;
                                   }                 
                                   num1[i]/=temp1;    
                                   num2[i]/=temp1;    
                               }
                               count+=cal(num3,len-1,k,lev);                                 
                           }                           
                       }
                 }                
                 break;

           case 2:    
                 if(k>max_k||k<-max_k) break;
                 if(num[0][0]==0)
                 {
                     for(j=1;j<len;j++)
                     {
                         num1[j-1]=num[0][j];
                         num2[j-1]=num[1][j];
                     }     
                     //add and minus when 0 occurs                
                     count+=cal(num3,len-1,k,lev);                      
                     num1[0]=-num1[0];                     
                     count+=cal(num3,len-1,k,lev);                                      
                 }
[/code]

27 楼


[code=c]
/*********************************************************************************
*             Written by jowenshaw, 16 Oct 2008.
*                       Compiled by
*             DEV-C++ 4.9.9.9.2  && TC++ 3.0 && VC++ 6.0
**********************************************************************************
                 else
                 {    
                     if(num[1][0]<=max2/num[1][1])
                     {
                         temp1=num[1][0]>0?num[1][0]:-num[1][0];
                         temp2=num[1][1]>0?num[1][1]:-num[1][1];
                         while(temp2!=0)
                         {
                              temp=temp2;
                             temp2=temp1%temp2;
                             temp1=temp;
                         }    
                         t=temp1;//gcd of num[1][0] and num[1][1]
                         temp1=num[0][0]/num[1][0];
                         temp2=num[0][1]/num[1][1];
                         t1=num[0][0]%num[1][0];
                         t2=num[0][1]%num[1][1];

                         num2[0]=num[1][0]/t*num[1][1];
                         for(j=2;j<len;j++)
                         {
                             num1[j-1]=num[0][j];
                             num2[j-1]=num[1][j];
                         }     

                         //add
                         num1[0]=num[1][1]/t*t1+num[1][0]/t*t2;                 
                         temp=num1[0]/num2[0];                 
                         num1[0]%=num2[0];
                         if(num1[0]==0)
                         {
                             num2[0]=1;
                         }                         
                         count+=cal(num3,len-1,k-temp1-temp2-temp,lev);

                         //minus
                         num1[0]=num[1][1]/t*t1-num[1][0]/t*t2;                 
                         temp=num1[0]/num2[0];                 
                         num1[0]%=num2[0];
                         if(num1[0]==0)
                         {
                             num2[0]=1;
                         }                     
                         count+=cal(num3,len-1,k-temp1+temp2-temp,lev);        
                     }
                 }
      }   
      
      free(num1);
      free(num2);
      return count;  
}
[/code]

28 楼


[size=5][/size][color=800000][/color]

[b]终于成功上传了,自我奖励一个。在精彩纷呈的奥运期间花了几个晚上写完以上程序,加油!编程无极限![/b]

29 楼

#include <iostream>
#include <cstdlib>
using namespace std;

int b[13],c[13],Max[13],Min[13]; 
int a[13];
int s;
int temp;
int k;
int ans = 0;

void dp(int x,int k)
{
    if(x==0)
    {
        if(c[0]==k)
            ans++;
        return;
    }
    if(Max[x]<k||Min[k]>k)
        return;
    dp(x-1,k-c[x]);
    dp(x-1,k+c[x]);
}

void cc(int n)
{
    int N = 1;
    int l;
    int i,j;
    for(i = 0; i < n-1; i++)
        N *= 3;
    for(i = 0; i < N; i++)
    {
         s = i;
         l = 0;
         c[0] = b[0];
         for(j = 1; j < n; j++)
         {
             temp = s%3;
             s/=3;
             if(temp==1)
                 c[l]*=b[j];
             else if(temp==2)// 
             {
                 if(b[j]==0||c[l]%b[j])
                     break;
                 c[l]/=b[j];
             }
             else
             {
                 l++;
                 c[l] = b[j];
             }
         }
         if(j<n)
             continue;
         l++;
         Min[0] = Max[0] = c[0];
         for(j = 1; j < l; j++)
         {
             Max[j] = Max[j-1]+c[j];
             Min[j] = Min[j-1]-c[j];
         }
         dp(l-1,k);
    }
}

void add(int n) //首先确定数的组合,共4096种 
{
     int l;
     int jin;
     int N = 1;
     for(int i = 0; i < n-1; i++)
         N *= 2;
    for(int i = 0; i < N; i++)
    {
         s = i;
         l = 0;
         b[0] = a[n-1];
         jin = 1;
         for(int j = n-2; j >= 0; j--)
         {
             temp = s%2;
             s/=2;
             if(temp==1)
             {
                 jin*=10;
                 b[l]+=jin*a[j];
             }
             else
             {
                 l++;
                 jin = 1;
                 b[l] = a[j];
             }
         }
         l++;
         for(int j = 0; j < l/2; j++)
         {
             jin = b[j];
             b[j] = b[l-j-1];
             b[l-j-1] = jin;
         }
         cc(l);
    }


int main(void)
{
    int n;
    cin >> n;
    for(int i = 0; i < n; i++)
        cin >> a[i];
    cin >> k;
    add(n);
    cout << ans << endl;
    return 0;
}

30 楼

诶。。。
我家DEV莫名其妙出问题

竟然擅自删除了我 3000 行的源文件
现在就剩100行了。。。
你说奇怪不奇怪吧!!!

删除的文件就是这次比赛的文件。。。
我难过啊。。。

71次快来吧!
(下次大家写源代码时请切记:随时备份!!!不要让我的悲剧重演!!!我用的DEV)

我来回复

您尚未登录,请登录后再回复。点此登录或注册