荔园在线
荔园之美,在春之萌芽,在夏之绽放,在秋之收获,在冬之沉淀
[回到开始]
[上一篇][下一篇]
发信人: dynamic (dynamic), 信区: Program
标 题: 贴答案了
发信站: 荔园晨风BBS站 (2006年01月03日22:19:46 星期二), 站内信件
一、简单题
这种问题,会的就不屑答,不会的就baidu一下. 这里略过了, sorry..
二、
////////////////////////////////////////////////////////////////////////
/////////////////
6. 阶乘, code如下:
# include <stdio.h>
# include <math.h>
# define MAX 100000
int res[MAX]; //储存结果,每一个int保留4位整数,所以n!在4*MAX位以内时,
算法保证正确.
int max_n() //计算当内存是MAX时,可计算的n是多少.
{
/*
n!的位数 = log10(n!) 取整后加1. 故
n!的位数 = log10(1)+log10(2)+...+log10(n)取整加1.
当然,也可以用Stirling逼近公式来计算,这样快好多,
不过考虑到贵公司的工程师数学水平有限,可能看不懂,
所以还是用这个方法来计算就算了.
*/
double ans=0;
int i;
for(i=1;;i++) {
ans+=log10(i);
if(floor(ans)+1>=4*MAX) break;
}
return i-1;
}
void Factor(int n)
{
int i,carry,j,digit;
if( n>max_n() || n<0) {
printf("n is too large! or n is negative!\n");
return ;
// max_n()可以先做预处理.
// 当然,也可以用max_n()中的方法,计算出n!的位数后再动态开辟内
存
,不过
我不喜欢这样. ^_^
}
res[0]=1;
digit=0;
for(i=1;i<=n;i++) {
carry=0;
for(j=0;j<=digit;j++) {
res[j]=res[j]*i+carry;
carry=res[j]/10000;
res[j]%=10000;
}
while(carry) digit++,res[digit]=carry%10000,carry/=10000;
}
printf("%d",res[digit]);
for(i=digit-1;i>=0;i--) printf("%.4d",res[i]);
printf("\n");
}
int main()
{
int n;
while(scanf("%d",&n)!=EOF) Factor(n);
return 0;
}
////////////////////////////////////////////////////////////////////////
/////////////////////
7. 求F_n
//递归版本..不考虑高精度大数了,反正这是体力活,以免大家看得辛苦.
# include <stdio.h>
# include <string.h>
# define MAX 1000000
long long F[MAX];
bool haveBeenCal[MAX]; //递归防止重复计算.
long long Cal(int n)
{
if(haveBeenCal[n]) return F[n];
haveBeenCal[n]=1;
return F[n]=Cal(n-1)-Cal(n-3);
}
int main()
{
int n;
memset(haveBeenCal,0,sizeof(haveBeenCal));
haveBeenCal[0]=haveBeenCal[1]=haveBeenCal[2]=1;
F[0]=0,F[1]=1,F[2]=2;
while(scanf("%d",&n)!=EOF) {
if(n<0||n>=MAX) printf("inavailabe n\n");
printf("%lld\n",Cal(n));
}
return 0;
}
//非递归版本
# include <stdio.h>
# define MAX 100000
int F[MAX];
int main()
{
int n,i,max;
F[0]=0,F[1]=1,F[2]=2;
max=2;
while(scanf("%d",&n)!=EOF) {
if(n<=max) {
printf("%d\n",F[n]);
continue;
}
for(i=max+1;i<=n;i++) F[i]=F[i-1]-F[i-3];
max=n;
printf("%d\n",F[n]);
}
return 0;
}
注: 对于这一题,我们还有另一个算法,对于一个n,不用一步一步地推n次,只要
推lg(n)次就可以了.
这是因为
_ _ - - - -
| F[n] | | 1 0 -1 | | F[n-1] |
| F[n-1] | = | 0 0 0 | *| F[n-2] |
| F[n-2] | | 0 1 0 | | F[n-3] |
- - - - - -
再推下去,得:
_ _ - - ^(n-2) - -
| F[n] | | 1 0 -1 | | F[2] |
| F[n-1] | = | 0 0 0 | * | F[1] |
| F[n-2] | | 0 1 0 | | F[0] |
- - - - - -
于是,问题就转化成如何求一个矩阵的n次方了,用分治的思想就可以做到lg(n)咯
,好简单,这里略,
可以参考素数判写的Miller-Rabin算法..kaka.
////////////////////////////////////////////////////////////////////////
/////////////
8. 链表排序
//直接修改一下Mergesort就可以了,nlogn
# include <stdio.h>
typedef struct _node_t{
int a;
struct _node_t* next;
}node_t;
node_t* Mergesort(node_t* L,int count) //链表头及要链表元数个数
{
if(count==1) return L;
int count1=count/2;
int count2=count-count1;
node_t* p=L;
int i;
for(i=0;i<count1;i++) p=p->next;
node_t* h1=Mergesort(L,count1);
node_t* h2=Mergesort(p,count2);
int t1=0,t2=0;
node_t *head=NULL,*cur;
while(t1<count1||t2<count2) {
if(t1<count1&&t2<count2) {
if(h1->a < h2->a) p=h1,h1=h1->next,t1++;
else p=h2,h2=h2->next,t2++;
}
else if(t1<count1) p=h1,h1=h1->next,t1++;
else p=h2,h2=h2->next,t2++;
if(head==NULL) head=cur=p;
else {
cur->next=p;
cur=p;
}
}
return head;
}
void sort(node_t* &a)
{
int count=0;
node_t* p=a;
while(a) {
count++;
a=a->next;
}
a=Mergesort(p,count);
p=a;
int i;
for(i=0;i<count-1;i++) p=p->next;
p->next=NULL;
}
void input(node_t* &a)
{
a=NULL;
int n;
node_t* p;
while(scanf("%d",&n)!=EOF) {
node_t* s= new node_t;
s->a=n;
if(a==NULL) a=p=s;
else p->next=s;
p=s;
p->next=NULL;
}
}
void output(node_t* a)
{
while(a) {
printf("%d ",a->a);
a=a->next;
}
printf("\n");
}
int main()
{
node_t* a;
//freopen("test.in","r",stdin);
input(a);//屏幕输入时输一串数字,然后按enter再按ctrl+z结束
sort(a);
output(a);
return 0;
}
////////////////////////////////////////////////////////////////////////
/
三、
9、集合合并
(1) 主要思路
关键就是两步:
1. 确定那些集合要合成一堆.
2. 如何合并一堆集合.
(2) 算法
1. 每个元素对应一个桶,装含有该元素的集合的编号.
如例子中:
{aaa}: 1
{bbb}: 1 2
{ccc}: 1
{ddd}: 2 5
{eee}: 3
{fff}: 3
{ggg}: 4
{hhh}: 5
这一步须时(所有集合中元素个数的总和).
2. 然后用并查集,每个桶中相邻的两个集合就要合并.
如上例,集合1,2,5要合并,其它独立.
这步须时, 总元素个数*a(总元素个数)
其中a(n)是Ackman函数的反函数,一般<=4,所以也大约地关于总元素个数成线
性.
3. 合并集合
例如,现在要分别合并集合的编号为1,2,5及集合编号为3,4,6的集合.
那么,我们就把集合1,2,5中含有的元素都标记为1.
再把3,4,6中含的元素都标记为2.
然后把所有元素扫一次,按标号分类就可以了.
复杂度,O(总元素个数).
综上,复杂度大约是O(总元素个数).
当然,这里不包括由给每个元素编号的复杂度,其实复杂度不高的吧,就是用最弱智
的方法就可以做到
不同元素的个数*log(不同元素的个数).
(3)改进
有比上面的算法快的话你通知一声我,谢谢.
: 【 在
: dynamic (dynamic) 的大作中提到: 】: 这是第一大题的
: //ps,baidu好白痴,它的网页做成不可以copy题目,但系查看一下源文件就copy了,
: //呵呵.
: 1. 请列举你所知道的Linux或者Windows进程间通迅的方式(请选择一种平台回答
: ,至少回答6个或以上)?
: 2. 实现一个TCP端口监听服务进程通常需要使用那些socket函数,并请描述这些函
: 数的作用?(至少回答6个或以上)
: 3. 将基于多进程模型的程序移植为基于多线程模型的程序,通常需要如何修改调
: 整程序(解决那些问题)?
: 4. 什么是C/C++的模板(template)编程, 有什么好处?
: .................(以下省略)
--
同人见面:how do u do !
____(```\一糸one .-'""""`-.二糸tow /```)____
笑 (____ \_____ / (O O) \ _____/ ____) 十 ┌————┐
一 (____ ( ) ) ____) 年 │笑脸小子│
笑 (____ _______\ \____/ /_____ __ ____) 少 └————┘
(______/ 我糸I `-.____.-' 你糸U \______)
※ 修改:·bakey 於 01月03日22:22:48 修改本文·[FROM: 210.21.224.233]
※ 来源:·荔园晨风BBS站 bbs.szu.edu.cn·[FROM: 210.21.224.233]
[回到开始]
[上一篇][下一篇]
荔园在线首页 友情链接:深圳大学 深大招生 荔园晨风BBS S-Term软件 网络书店