ZOJ3380 Patchouli's Spell Cards C++版(概率DP+大数)

匿名 (未验证) 提交于 2019-12-03 00:25:02

题意题解不说了,这里主要讲用C++大数

为了节省时间使用了进制压缩,使用long long数组,进制1e9,使进制的平方在long long范围内

1290ms 4836KB

#include<stdio.h> #include<string.h> #include<algorithm> using namespace std; const long long mod=1000000000; struct biginteger {     long long number[26];     int len;     biginteger operator+(biginteger &b)     {         int i,root=max(len,b.len),Len=1;         biginteger ans;         memset(ans.number,0,sizeof(ans.number));         ans.len=1;         for(i=0; i<root||ans.number[i]; i++)         {             ans.number[i]+=number[i]+b.number[i];             if(ans.number[i]>=mod)             {                 ans.number[i+1]+=ans.number[i]/mod;                 ans.number[i]%=mod;             }             if(ans.number[i])                 Len=i;         }         ans.len=Len+1;         return ans;     }     biginteger operator-(biginteger &b)     {         int i,root=max(len,b.len),Len=0;         biginteger ans;         memset(ans.number,0,sizeof(ans.number));         ans.len=1;         for(i=0; i<root; i++)         {             ans.number[i]+=number[i]-b.number[i];             if(ans.number[i]<0)             {                 ans.number[i+1]-=1;                 ans.number[i]+=mod;             }             if(ans.number[i])                 Len=i;         }         ans.len=Len+1;         return ans;     }     biginteger operator*(biginteger &b)     {         int i,j,root=0;         biginteger ans;         memset(ans.number,0,sizeof(ans.number));         ans.len=1;         for(i=0; i<len; i++)         {             for(j=0; j<b.len; j++)                 ans.number[i+j]+=number[i]*b.number[j];         }         for(i=0; i<=len+b.len||ans.number[i]; i++)         {             if(ans.number[i]>=mod)             {                 ans.number[i+1]+=ans.number[i]/mod;                 ans.number[i]%=mod;             }             if(ans.number[i])                 root=i;         }         ans.len=root+1;         return ans;     }     bool Greater(biginteger b)     {         if(len>b.len)             return true;         if(len<b.len)             return false;         int i;         for(i=len-1; i>=0; i--)         {             if(number[i]>b.number[i])                 return true;             if(number[i]<b.number[i])                 return false;         }         return true;     }     biginteger operator/(biginteger &b)     {         biginteger ans_quotient;         biginteger ans_remainder;         memset(ans_quotient.number,0,sizeof(ans_quotient.number));         ans_quotient.len=1;         memset(ans_remainder.number,0,sizeof(ans_remainder.number));         ans_remainder.len=1;         biginteger temp;         int i,j,root=0;         long long w,head=0,l,r,mid;         for(i=len-1; i>=b.len-1; i--)         {             head*=mod;             head+=number[i];             l=head/(b.number[b.len-1]+1);             r=head/b.number[b.len-1];             while(l<=r)             {                 mid=(l+r)/2;                 memset(temp.number,0,sizeof(temp.number));                 temp.len=1;                 temp.number[i-b.len+1]=mid;                 temp.len=i-b.len+2;                 temp=temp*b;                 if(Greater(temp))                     l=mid+1;                 else                     r=mid-1;             }             w=max(r,(long long)0);             memset(temp.number,0,sizeof(temp.number));             temp.len=1;             temp.number[i-b.len+1]=w;             temp.len=i-b.len+2;             temp=temp*b;             int xroot=max(len,temp.len);             for(j=0; j<xroot; j++)             {                 number[j]-=temp.number[j];                 if(number[j]<0)                 {                     number[j+1]-=1;                     number[j]+=mod;                 }                 if(number[j])                     len=j+1;             }             ans_quotient.number[i-b.len+1]=w;             head=number[i];             if(root==0&&w!=0)                 root=i-b.len+2;         }         ans_quotient.len=max(root,1);         for(i=0; i<len; i++)             ans_remainder.number[i]=number[i];         ans_remainder.len=1;         for(i=len-1; i>=0; i--)         {             if(ans_remainder.number[i])             {                 ans_remainder.len=i+1;                 break;             }         }         return ans_quotient;     }     biginteger operator%(biginteger &b)     {         biginteger ans_quotient;         biginteger ans_remainder;         memset(ans_quotient.number,0,sizeof(ans_quotient.number));         ans_quotient.len=1;         memset(ans_remainder.number,0,sizeof(ans_remainder.number));         ans_remainder.len=1;         biginteger temp;         int i,j,root=0;         long long w,head=0,l,r,mid;         for(i=len-1; i>=b.len-1; i--)         {             head*=mod;             head+=number[i];             l=head/(b.number[b.len-1]+1);             r=head/b.number[b.len-1];             while(l<=r)             {                 mid=(l+r)/2;                 memset(temp.number,0,sizeof(temp.number));                 temp.len=1;                 temp.number[i-b.len+1]=mid;                 temp.len=i-b.len+2;                 temp=temp*b;                 if(Greater(temp))                     l=mid+1;                 else                     r=mid-1;             }             w=max(r,(long long)0);             memset(temp.number,0,sizeof(temp.number));             temp.len=1;             temp.number[i-b.len+1]=w;             temp.len=i-b.len+2;             temp=temp*b;             int xroot=max(len,temp.len);             for(j=0; j<xroot; j++)             {                 number[j]-=temp.number[j];                 if(number[j]<0)                 {                     number[j+1]-=1;                     number[j]+=mod;                 }                 if(number[j])                     len=j+1;             }             ans_quotient.number[i-b.len+1]=w;             head=number[i];             if(root==0&&w!=0)                 root=i-b.len+2;         }         ans_quotient.len=max(root,1);         for(i=0; i<len; i++)             ans_remainder.number[i]=number[i];         ans_remainder.len=1;         for(i=len-1; i>=0; i--)         {             if(ans_remainder.number[i])             {                 ans_remainder.len=i+1;                 break;             }         }         return ans_remainder;     }     bool operator==(biginteger &b)     {         if(len!=b.len)             return false;         int i;         for(i=0; i<len; i++)         {             if(number[i]!=b.number[i])                 return false;         }         return true;     }     bool operator!=(biginteger &b)     {         if(len!=b.len)             return true;         int i;         for(i=0; i<len; i++)         {             if(number[i]!=b.number[i])                 return true;         }         return false;     } } c[105][105],dp[105][105],zero,one; void Print(biginteger a); biginteger Gcd(biginteger a,biginteger b) {     while(b!=zero)     {         biginteger temp=b;         b=a%b;         a=temp;     }     return a; } void Print(biginteger a) {     int i;     printf("%lld",a.number[a.len-1]);     for(i=a.len-2; i>=0; i--)         printf("%09lld",a.number[i]); } int main() {     one.len=1;     one.number[0]=1;     zero.len=1;     int i,j,k;     for(i=0; i<=100; i++)         c[i][0]=c[i][i]=one;     for(i=2; i<=100; i++)     {         for(j=1; j<i; j++)             c[i][j]=c[i-1][j-1]+c[i-1][j];     }     long long n,m,l;     while(~scanf("%lld%lld%lld",&m,&n,&l))     {         if(l>m)         {             printf("mukyu~\n");             continue;         }         for(i=0; i<=100; i++)         {             for(j=0; j<=100; j++)                 dp[i][j]=zero;         }         dp[0][0]=one;         biginteger ans=zero;         for(i=1; i<=n; i++)         {             for(j=1; j<=m; j++)             {                 for(k=0; k<=j&&k<l; k++)                 {                     biginteger temp=dp[i-1][j-k]*c[m-(j-k)][k];                     dp[i][j]=dp[i][j]+temp;                 }             }             ans=ans+dp[i][m];         }         biginteger sum=one;         for(i=0; i<m; i++)         {             biginteger x=zero;             x.number[0]=n;             sum=sum*x;         }         ans=sum-ans;         biginteger gcd=Gcd(sum,ans);         Print(ans/gcd);         printf("/");         Print(sum/gcd);         printf("\n");     }     return 0; }

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!