关于北大acm1745问题分析讨论

nobush 2006-05-04 01:22:08
以下依次给出题目、我的分析、代码 ,我是第一次作acm,总是通不过,请大家帮忙参考一下。

http://acm.pku.cn/JudgeOnline/showproblem?problem_id=1745
中文大意(好像我没理解错吧?)
对N(1<=N<=10000)个数字,在数字之间添加加号或者减号,每个组合可以计算出一结果。判断这些结果中是否存在能够被K(2<=K<=100)除尽的数字。
比如对:17, 5, -21, 15这4个数字,添加加号或者减号可以得到:
17 + 5 + -21 + 15 = 16
17 + 5 + -21 - 15 = -14
17 + 5 - -21 + 15 = 58
17 + 5 - -21 - 15 = 28
17 - 5 + -21 + 15 = 6
17 - 5 + -21 - 15 = -24
17 - 5 - -21 + 15 = 48
17 - 5 - -21 - 15 = 18
如果K为7,那么可以说:存在17 + 5 + -21 - 15 = -14 能被7除尽。

输入格式:
数据第一行有两个整数,N(1<=N<=10000),K(2<=K<=100)。数字之间由空格分开。第二行是N个数字,他们的绝对值不超过10000,数字之间由空格分开。

输出格式:
如果存在一个组合能被K除尽,那么输出"Divisible",否则输出"Not divisible"。

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

分析:
一、此题考察结果是否整除,即表示为是否有余数;

二、N个数相加减,所的结果除以K的余数,等于它们各自对K的余数相加减;

三、这些余数计算的结果可能会有重复的,并且只落在[0,K)范围内;

四、因此,不必列出N个数相加减的所有组合,只需从头开始逐步计算结果(并取余),每一步的结果再加减下一个,直到最后产生最终不超过K个的结果;

五、上述表达用数学描述为:设 计算到第n个的结果为集合A,下一个余数为b,则第n+1个结果为{t+b,t-b|t属于A};

六、考察最后的结果集合中是否有0,即表示有无整除项。

程序采用C语言,数组方案,用大小为K的数组表示某一步的结果集合,元素用1,0表示有无相应的余数项,如:某一步有结果为i,则令p[i]=1;
为方便计算设两个数组,p1是上一步的结果集合,运算时先把p2清零,把p1中元素为1的项数逐个拿来计算,结果映射到p2中去,完成后交换两个数组,进入下一步;
读数的时候第一个数据单独处理(因为没有0+t,0-t),后面的数据用循环;
最后判断p1[0]是否为1即可。

~~~~~~~~~~~~~~~~~~~~~~~~

代码:
#include<stdio.h>

int main()
{
int n,k,i,d,c,t;
char *p1,*p2,*pt;
char a[100],b[100];
scanf("%d%d", &n, &k);
p1=a;
p2=b;
scanf("%d",&d);
d%=k;
if(d<0)d+=k;
for(i=0;i<k;i++)
p1[i]=0;
p1[d]=1;
c=0;
while(--n)
{
scanf("%d",&d);
if(c)continue;
d%=k;
if(!d)continue;
if(d<0)d+=k;
for(i=0;i<k;i++)
p2[i]=0;
c=0;
for(i=0;i<k;i++)
{
if(p1[i])
{
c++;
t=i+d;
if(t>=k)t-=k;
p2[t]=1;
t=i-d;
if(t<0)t+=k;
p2[t]=1;
}
}
if(c!=k)
{
c=0;
pt=p1;
p1=p2;
p2=pt;
}
}
if(*p1||c)
puts("Divisible");
else
puts("Not divislble");
return 0;
}


...全文
321 15 打赏 收藏 转发到动态 举报
写回复
用AI写文章
15 条回复
切换为时间正序
请发表友善的回复…
发表回复
liuguangliang 2006-05-09
  • 打赏
  • 举报
回复
好办法
要顶
languagec 2006-05-09
  • 打赏
  • 举报
回复
楼主真是很聪明的想法
yuxh 2006-05-09
  • 打赏
  • 举报
回复
楼主的想法是正确的吧
int is_divisible(int *ary, int num, int k)
{
int *fac1 = (int *)malloc(sizeof(int) * k);
int *fac2 = (int *)malloc(sizeof(int) * k);

char *flag = (char *)malloc(k);
int i, j, cur, len = 1, idx, ret;
fac1[0] = 0;
for(i=0; i<num; i++) {
if(ary[i]%k==0)continue;
memset(flag, 0, k);
cur = 0;
for(j=0; j<len; j++) {
idx = (fac1[j] + ary[i]) % k;
if(flag[idx] == 0) {
flag[idx] = 1;
fac2[cur++] = idx;
}
idx = k - idx;
if(flag[idx] == 0) {
flag[idx] = 1;
fac2[cur++] = idx;
}
}
ret = flag[0] == 1;
free(fac1);
free(fac2);
free(flag);
return ret;
}

int main()
{
int i, num, k;
int *ary;
scanf("%d %d",&num,&k);
ary = (int *)malloc(sizeof(int) * num);
for (i=0;i<num;i++) {
scanf("%d",&ary[i]);
}
if(is_divisible(ary, num, k))
printf("Divisible\n");
else
printf("Not divisible\n");

free(ary);
}
tzxyc 2006-05-09
  • 打赏
  • 举报
回复
ding
tailzhou 2006-05-09
  • 打赏
  • 举报
回复
1211884 tailzhou 1745 Accepted 24K 60MS C++ 0.76K 2006-05-09 13:33:27.0
tailzhou 2006-05-09
  • 打赏
  • 举报
回复
puts("Not divislble");
return 0;
}

原来你的divisl(l<>i)ble写错了,晕!!!
caiyujie87 2006-05-06
  • 打赏
  • 举报
回复
mark
king_water 2006-05-06
  • 打赏
  • 举报
回复
我写了一个但超时

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

int a[10000];
int n,k;
void work(int i,int sum)
{
if ( sum >= k )
sum -= k;
else if ( sum <=-k )
sum += k;
if (i==n)
{
if (sum ==0)
{
printf("Divisible\n");
exit(0);
}
}
else
{
work(i+1,sum+a[i]);
work(i+1,sum-a[i]);
}
}
int main()
{
int i;
scanf("%d%d",&n,&k);
if ( k < 0 )
k = -k;
for (i=0;i<n;i++)
{
scanf("%d",&a[i]);
if ( a[i] < 0 )
a[i] = -a[i];
a[i] %= k;
}
work(1,a[0]);
printf("Not divisible\n");
return 0;
}
nobush 2006-05-05
  • 打赏
  • 举报
回复
to f_acme

if(d<0)d+=k;一句前面还有d%=k;所以应该不会有d<-k的情况。

to jixingzhong
不是超时,而是直接给出Wrong Answer
striker_un 2006-05-05
  • 打赏
  • 举报
回复
顶。
jixingzhong 2006-05-04
  • 打赏
  • 举报
回复
楼主计算时间超了吧 ?
加减运算 和 求余比较的话 ...
jixingzhong 2006-05-04
  • 打赏
  • 举报
回复
...
只有 + -还出错 ?
24点还考虑 * /,
还要考虑括号 ...
那不晕了?
f_acme 2006-05-04
  • 打赏
  • 举报
回复
还有一些特殊情况比如只有一个数的情况,这些往往就是出错的原因。
f_acme 2006-05-04
  • 打赏
  • 举报
回复
中间有一句if(d<0)d+=k;可能会出现错,如果当d<-k时,这样的结果还是负数。
另外不知你用puts()会不会出错,最后用printf()拉。
niatclock 2006-05-04
  • 打赏
  • 举报
回复
MARK

69,371

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧