有一段时间没做ACM了,都有些忘了,现在捡起来再练练手。这是一道数学题目,出题者的英文真是恶心得不得了,这题的意思说的真是让人不容易明白。我也是读了好久,然后不确定,就看了下别人的理解,下面贴一个别人的理解:
这道题的意思说得糊里糊涂的……大概意思是这样吧(反正按以下理解能做出AC code):一套彩票有n张,编号由1到n,凑齐这n张能得奖,问平均每买几张彩票会得到完整的一套彩票。(不是直译,这只是我理解的题目的大意,注意“平均每买几张……”),这大概是一个数学期望的问题吧。以n=3为例,要凑齐1、2和3,买一张彩票无论是1、2还是3都是所需的,买中所需彩票的概率是1,期望的买的张数也是1;再买一张,现在需要的是2或3,一次买中所需的彩票的概率为2/3,忽略张数是int,假设平均每买x张(不是每买x张就一定有,而是平均)就能得到所需的,有(2/3)*x=1,于是x=1/(2/3);假设得到2,现在需要3,买一张是3的概率是1/3,显然平均每买1/(1/3)=3张就有一张3.所以sum=1+1/(2/3)+1/(1/3)。
题意明白了,下面就是我们要看的答案就是求:n/1+n/2+n/3+----+n/n!,这个式子是一个发散的,n无穷大的时候,结果无限大,这个是没有一个公式的,所以题目规定的1<=n<=22就是这个意思,那么我们通分之后分母是n!,22!也会超过long long所以直接算肯定是不行的,那么我们想通分,通分,不就是求最小公倍数?对了,求所有的数字的最小公倍数就不会超了,你可以看10,20一下子就小了10倍,算一下肯定不会超得。
#include<iostream>
using namespace std;
long long gcd(long long a , long long b) //分子,分母约分
{
if(b==0)return a;
return gcd(b,a%b);
}
int main()
{
long long sum1,sum2,i,k,num;
int j1,j2;
long long N;
while(cin>>N)
{
j1=j2=0;
sum1=1;
sum2=0;
k=0;
if(N==1){cout<<"1"<<endl;continue;}
if(N==2){cout<<"3"<<endl;continue;}
for(i=1;i<=N;i++)
sum1=sum1*i/gcd(sum1,i); //最小公倍数等于成绩除以最大公约数
for(i=1;i<=N;i++)
sum2+=sum1/i;
sum2*=N;
k=sum2/sum1; //整数部分
if(sum2%sum1==0)cout<<k<<endl;
else
{
num=sum2%sum1;
i=gcd(sum1,num);
num/=i;
sum1/=i;
i=k;
while(i/10!=0) //算整数部分的位数,需要空格的
{
i/=10;
j1++;
}
for(i=0;i<=j1+1;i++)
cout<<" ";
cout<<num<<endl;
cout<<k<<" ";
i=sum1;
while(i/10!=0) //算分母的位数同上
{
i/=10;
j2++;
}
for(i=0;i<=j2;i++)
cout<<"-";
cout<<endl;
for(i=0;i<=j1+1;i++)
cout<<" ";
cout<<sum1<<endl;
}
}
return 0;
}
这道题的意思说得糊里糊涂的……大概意思是这样吧(反正按以下理解能做出AC code):一套彩票有n张,编号由1到n,凑齐这n张能得奖,问平均每买几张彩票会得到完整的一套彩票。(不是直译,这只是我理解的题目的大意,注意“平均每买几张……”),这大概是一个数学期望的问题吧。以n=3为例,要凑齐1、2和3,买一张彩票无论是1、2还是3都是所需的,买中所需彩票的概率是1,期望的买的张数也是1;再买一张,现在需要的是2或3,一次买中所需的彩票的概率为2/3,忽略张数是int,假设平均每买x张(不是每买x张就一定有,而是平均)就能得到所需的,有(2/3)*x=1,于是x=1/(2/3);假设得到2,现在需要3,买一张是3的概率是1/3,显然平均每买1/(1/3)=3张就有一张3.所以sum=1+1/(2/3)+1/(1/3)。
题意明白了,下面就是我们要看的答案就是求:n/1+n/2+n/3+----+n/n!,这个式子是一个发散的,n无穷大的时候,结果无限大,这个是没有一个公式的,所以题目规定的1<=n<=22就是这个意思,那么我们通分之后分母是n!,22!也会超过long long所以直接算肯定是不行的,那么我们想通分,通分,不就是求最小公倍数?对了,求所有的数字的最小公倍数就不会超了,你可以看10,20一下子就小了10倍,算一下肯定不会超得。
#include<iostream>
using namespace std;
long long gcd(long long a , long long b) //分子,分母约分
{
if(b==0)return a;
return gcd(b,a%b);
}
int main()
{
long long sum1,sum2,i,k,num;
int j1,j2;
long long N;
while(cin>>N)
{
j1=j2=0;
sum1=1;
sum2=0;
k=0;
if(N==1){cout<<"1"<<endl;continue;}
if(N==2){cout<<"3"<<endl;continue;}
for(i=1;i<=N;i++)
sum1=sum1*i/gcd(sum1,i); //最小公倍数等于成绩除以最大公约数
for(i=1;i<=N;i++)
sum2+=sum1/i;
sum2*=N;
k=sum2/sum1; //整数部分
if(sum2%sum1==0)cout<<k<<endl;
else
{
num=sum2%sum1;
i=gcd(sum1,num);
num/=i;
sum1/=i;
i=k;
while(i/10!=0) //算整数部分的位数,需要空格的
{
i/=10;
j1++;
}
for(i=0;i<=j1+1;i++)
cout<<" ";
cout<<num<<endl;
cout<<k<<" ";
i=sum1;
while(i/10!=0) //算分母的位数同上
{
i/=10;
j2++;
}
for(i=0;i<=j2;i++)
cout<<"-";
cout<<endl;
for(i=0;i<=j1+1;i++)
cout<<" ";
cout<<sum1<<endl;
}
}
return 0;
}