一道旧题

dcyu 2003-01-19 10:20:23
整数序列
对于任意的3个正整数N、P、Q
编程确定是否存在这样一个含N个整数的整数序列,使得序列中任意的P个连续整数之和为正,使得序列中任意的P个连续整数之和为正,而对任意Q个连续整数之和为负。
如果存在这样的序列,请输出该序列,否则输入“NO”
输入文件 input.txt 格式为 N P Q
输出文件 output.txt "NO"或满足条件的一个整数序列
________________________________
示例 input.txt output.txt
N P Q
 ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄
1 4 2 3 NO
 ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄
2 6 5 3 -3 5 -3 -3 5 -3
 ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄
8月份的时候有人提出,现在那个帖子被删了,当时我写了一个程序,但是没有办法通过所有的测试数据。
谁能提供一下算法或是程序?
...全文
36 12 打赏 收藏 转发到动态 举报
写回复
用AI写文章
12 条回复
切换为时间正序
请发表友善的回复…
发表回复
dcyu 2003-01-22
  • 打赏
  • 举报
回复
谢谢了。问题解决了。
我多虑了,构造等差数列s的公差是1,然后推回去是没有问题的。
也多谢你的朋友。结帖了。
修改后如下:
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>

#define M 1000

void main()
{
int s[M+1],a[M+1];
int tag[2*M+1];
int i,j,k,m,n;
int t,sum;
int N,P,Q,bN;
clrscr();
scanf("%d",&N);
scanf("%d",&P);
scanf("%d",&Q);
if(P+Q-2<N||P<=Q/2||Q<=P/2||P==Q||P>N||Q>N) { printf("NO!\n"); exit(1); }
bN=N;
N=P+Q-2;
tag[N]=1; i=1; j=1; m=N; n=N;
while(i!=P-1)
{
m--;
if(i+Q<=N) { tag[m]=i+Q; i=i+Q; }
else if(i-P>=0) { tag[m]=i-P; i=i-P; }
else { printf("Error!"); exit(1); }
}
while(j!=Q-1)
{
n++;
if(j+P<=N) { tag[n]=j+P; j=j+P; }
else if(j-Q>=0) { tag[n]=j-Q; j=j-Q; }
else { printf("Error!"); exit(1); }

}

for(k=m;k<=n;k++)
if(tag[k]==0) { s[0]=0; break; }
sum=0;
for(t=k+1;t<=n;t++)
{
sum++;
s[tag[t]]=sum;

}
sum=0;
for(t=k-1;t>=m;t--)
{
sum--;
s[tag[t]]=sum;

}
for(t=1;t<=bN;t++)
{
a[t]=s[t]-s[t-1];
printf("%d ",a[t]);
}

}
ZhangYv 2003-01-22
  • 打赏
  • 举报
回复
这个问题有答案了,请查看我给你发的短消息
dcyu 2003-01-21
  • 打赏
  • 举报
回复
自己up.
ZhangYv 2003-01-21
  • 打赏
  • 举报
回复
放假外出旅游,终止对此问题的谈论...
对不起哦,楼主。
huhairui3 2003-01-21
  • 打赏
  • 举报
回复
学习学习!
birth_chen 2003-01-21
  • 打赏
  • 举报
回复
帮你up
dcyu 2003-01-20
  • 打赏
  • 举报
回复
是啊,我也差不多是这么想的。现在的问题是什么情况下,问题是无解的?我原来的结论是:N<P+Q-2 且 (P>Q/2 或 Q>P/2)时有解,但是不对,很多时候满足这种情况,也就是你所说的“拓扑有序的(即不含圈)”,却无法构造出来解,而且我的程序在有些情况下运行出现了非法操作。
另外如果出现:...s[1+2*Q]<s[1+Q]<s[1]<s[1+P]<s[1+P-Q]<...
如何对上面的s数组附值?我原来是等差数列,公差是1,可是如果PQ不互素的话,构造的时候是不是公差为PQ的最大公约数?
up有分。
ZhangYv 2003-01-20
  • 打赏
  • 举报
回复
上述解法最关键的是两个不等式组:
Si > S(i-p) (p≤i≤n)
Si < S(i-q) (q≤i≤n)
对此你应该也会认同。
对S0到Sn排序这部分你有没什么疑问?要排序的对象从何而来,我对此做法不太理解...
ZhangYv 2003-01-20
  • 打赏
  • 举报
回复
不是我做出来的,你看看有没道理:
这题比较有意思,关键之处在于连续k个数之和的表示。我们可以利用连续这一特点,将其表示为S(i+k)-Si,这样的表示就使数学模型的建立容易些。我们记Si为数列中前i个整数之和,S0=0。根据题意,可以列出如下两组不等式:
Si > S(i-p) (p≤i≤n)
Si < Si-q (q≤i≤n)
问题有解的条件就是不等式是相容的。
由此可以建立一个有向图,共有n+1个顶点,分别是S0至Sn,若Si<Sj,那么就从Si往Sj引一条边。这样对于S0,S1,…,Sn来说,他们必须是拓扑有序的(即不含圈),反过来,任何一组S0…Sn都惟一地对应一个整数数列。因此,这道题目就转化为拓扑排序问题。
ZhangYv 2003-01-19
  • 打赏
  • 举报
回复
可能是等级比较高的比赛试题,否则没理由这么难,毫无头绪...
我承认我无知...

这种东西需要叫starfish出山了...

—————————————————————————————————
┏━★━━◆━━★━┓
♂欢|◢CSDN◣|使♂        ▲自由保存帖子,浏览,关注检测
┃迎|◥论坛助手◤|用┃        ▲完善的CSDN客户端工具
┗━☆━━◇━━━☆┛       ▲自动添加签名......

让你更快,更爽,更方便地上CSDN...
http://www.csdn.net/expert/topic/573/573604.xml
http://www.chinaok.net/csdn/csdn.zip
dcyu 2003-01-19
  • 打赏
  • 举报
回复
我的主页留了一个空缺,就是这道题没有想明白,特别是有时PQ不互素的时候出现点问题。大家来讨论一下吧。
dcyu 2003-01-19
  • 打赏
  • 举报
回复
这是我当时的解答:

根据单纯型法可以得出结论:
可以列出N个变量,但是却有P-1+Q-1行约束条件,
这些条件彼此独立,当N>P-1+Q-1时,矩阵的秩<=P+Q-2<N,
不满足线性规划中可行解的条件,因而不成立。
当P<Q/2 或 Q<P/2时矩阵的秩也不为N,所以也不成立。
因此就有结论:
当 N<=P+Q-2,
P>Q/2 或 Q>P/2
此时才能有解。
否则无解。
下面最复杂的就是构造问题了,我可是想了很长时间的。
先假设N=P+Q-2,若此时可以构造的出来,
那么N<P+Q-2就一定可以做出来(只要取前N项即可)。
增加第0个数为0;
设a[0]=0;s[0]=0;
令s[i]=a[1]+a[2]+...a[i];
那么就会有:
s[i+P]-s[i]>0
s[i+Q]-s[i]<0 (i=1...)
如果i从1开始,就可以得到一个排列:
...s[1+2*Q]<s[1+Q]<s[1]<s[1+P]<s[1+P-Q]<...

举个例子吧:
N=16,P=11,Q=7.
按照这种方法做下去就会得到:
s[10]<s[3]<s[14]<s[7]<s[0]<s[11]<s[4]<s[15]<s[8]<s[1]<s[12]<s[5]<s[16]<s[9]<s[2]<s[13];
其中s[0]=0,这样从0开始向左或向右得到:假设构造的一个排列
-4,-3,-2,-1,0,1,2,...11.
这就是s[i]的值,得到s[i]后,有a[i]=s[i]-s[i-1].
就可以得到序列:
5,5,-13,5,5,5,-13,5,5,-13,5,5,5,-13,5,5

程序在TC2.0下编译通过,如下:
/* pqn.c */
/* Author dcyu */
/* Date 2002 8 13 */

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

#define M 1000

void main()
{
int s[M+1],a[M+1];
int tag[2*M+1];
int i,j,k,m,n;
int t,sum;
int N,P,Q,bN;
clrscr();
scanf("%d",&N);
scanf("%d",&P);
scanf("%d",&Q);
if(P+Q-2<N||P>Q/2||Q>P/2) { printf("NO!\n"); exit(1); }
bN=N;
N=P+Q-2;
tag[N]=1; i=1; j=1; m=N; n=N;
while(i!=P-1)
{
m--;
if(i+Q<=N) { tag[m]=i+Q; i=i+Q; }
else if(i-P>=0) { tag[m]=i-P; i=i-P; }
else { printf("Error!"); exit(1); }
}
while(j!=Q-1)
{
n++;
if(j+P<=N) { tag[n]=j+P; j=j+P; }
else if(j-Q>=0) { tag[n]=j-Q; j=j-Q; }
else { printf("Error!"); exit(1); }

}

for(k=m;k<=n;k++)
if(tag[k]==0) { s[0]=0;break; }
sum=0;
for(t=k+1;t<=n;t++)
{
sum++;
s[tag[t]]=sum;

}
sum=0;
for(t=k-1;t>=m;t--)
{
sum--;
s[tag[t]]=sum;

}
for(t=1;t<=bN;t++)
{
a[t]=s[t]-s[t-1];
printf("%d ",a[t]);
}

}

另外用程序也可以验证,上述结论是正确的。
当P>Q时 最小的数是s[P-1],最大的是s[Q-1],

如果N>=P+Q-1,则还能有s[P+Q-1]<s[P-1],并且s[P+Q-1]>s[Q-1]
于是就有s[P+Q-1]<s[P-1]<...<s[Q-1]<s[P+Q-1].
显然是一个矛盾,所以N>P+Q-2是不正确的。于是也验证了结论。

33,009

社区成员

发帖
与我相关
我的任务
社区描述
数据结构与算法相关内容讨论专区
社区管理员
  • 数据结构与算法社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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