题目:已知并且
求最小的正数M,使得ak+1,ak···a0都是整数;
分母求最小公倍数就可以;
注意n^k的系数是C(k+1,1)*b1+(k+1);
注意最大公约数为负数的情况,强制转化为正数,用分子保存整个分数的正负性,因为题目要求最小的正数M
#include<iostream> #include<cstdio> #include<cstring> #include<string> #include<iomanip> #include<vector> #include<map> #include<algorithm> #include<cmath> using namespace std; typedef long long ll; const int maxn=25; ll c[maxn][maxn]; struct PP { ll a,b;//分子、分母 }; PP b[maxn],ans[maxn]; /*ll gcd(ll a,ll b) { if(b==0) return a; return gcd(b,a%b); }*/ ll gcd(ll a,ll b) { if(a%b==0) { if(b>0) return b; return -b; } return gcd(b,a%b); } PP add(PP a,PP b)//模拟两个分数的加法 { if(!a.a)//如果有一个为零 return b; if(!b.a) return a; ll temp=a.b/gcd(a.b,b.b)*b.b;//求出分母的最小公倍数 PP res; res.a=temp/a.b*a.a+temp/b.b*b.a;//分子相加 res.b=temp; if(res.a)//约掉最大公约数 { ll tt=gcd(res.a,res.b); res.b/=tt; res.a/=tt; } return res; } void init() { memset(c,0,sizeof(c)); for(int i=0;i<maxn;i++)//预处理组合数 { c[i][0]=c[i][i]=1; for(int j=1;j<i;j++) c[i][j]=c[i-1][j]+c[i-1][j-1]; } b[0].a=1;//求伯努利数 b[0].b=1; for(int i=1;i<=20;i++)//用递推关系求 { PP temp; temp.a=0; temp.b=0; for(int j=0;j<i;j++) { PP tt=b[j]; tt.a=tt.a*c[i+1][j]; if(tt.a) { ll te=gcd(tt.a,tt.b); tt.a/=te; tt.b/=te; } temp=add(temp,tt); } temp.a=-temp.a; temp.b*=c[i+1][i]; if(temp.a) { ll te=gcd(temp.a,temp.b); temp.a/=te; temp.b/=te; } else temp.b=0; b[i]=temp; } } int main() { init(); int k; while(~scanf("%d",&k)) { ll cur=1; for(int i=0;i<=k;i++) { if(i==1) { ans[i].a=k+1;//b[1]要加上后面多出来的n^k ans[i].b=2; } else { ans[i]=b[i]; ans[i].a*=c[k+1][i]; } if(ans[i].a)//约分 { ll temp=gcd(ans[i].a,ans[i].b); ans[i].a/=temp; ans[i].b/=temp; } else ans[i].b=0; if(ans[i].b)//求分母的最小公倍数 cur=cur/gcd(cur,ans[i].b)*ans[i].b; } printf("%lld ",cur*(k+1)); for(int i=0;i<=k;i++)//求出通分后每一项的系数 { if(ans[i].b) ans[i].a=cur/ans[i].b*ans[i].a; } for(int i=0;i<=k;i++) printf("%lld ",ans[i].a); printf("0\n");//最后一个一定为零 } }