zoukankan      html  css  js  c++  java
  • 【bzoj1300】大数计算器

    题意:

    求C(n,m) 如果C(n,m)的位数<=12 那么直接输出 否则按XXX...XXXXXXXXX的形式输出

    题解:

    这题之前打过 但是昨天又想出一种新的做法 先说下新的做法吧- -

    ________________(坑爹的博客园出现了一些bug 不能显示回车 so 我是华丽的分割线)________________

    首先要知道位数 显然可以用res存 如果是乘的res就加log(10,x) 除的就减掉

    如果res<13那么暴力算 直接输出就完了

    如果res>=13 就要知道前3位 和答案模10^10的值

    前3位很简单 把res的整数部分边成2 10^res的整数部分就是前3位

    后面要算C(n,m)%10^10的值 我们发现10^10=(2^10)*(5^10)

    就把要乘或除的数a 转换成a=a'*(2^x)*(5^y) (a',10)=1

    把2和5的次方分离出来算 那么就能保证运算的数都和10^10互质 就能用乘法逆元了

    _________________________________________________________________________________

    但是这有个问题- -

    10^10*10^10可能会爆long long

    对这问题有两种办法解决

    1.高精 不解释

    2.分别算模2^10 和模5^10 最后线性模方程算答案

    鉴于这两种方法都听难打 而且bzoj还把这题变成高富帅题 于是我放弃治疗了- -

    _________________________________________________________________________________

    正解:

    我们可以把每个数都分解质因数 因为n和m都比较小 所以可以把每个质数的指数都存下来 最后统一算就完了

    _________________________________________________________________________________

    代码:

     1 #include <cstdio>
     2 #include <cmath>
     3 using namespace std;
     4 typedef long long ll;
     5 const ll mo=1000000000000ll;
     6 ll n,m,ans=1,num,sum[1000001],bo[1000001],primer[1000001],ns;
     7 double save;
     8 ll power(ll a,ll b){
     9             ll res=1;
    10             for (;b;b>>=1){
    11                 if (b&1) res=res*a%mo;
    12                 a=a*a%mo;
    13             }
    14             return res;
    15 }
    16 void makepr(ll t){
    17      for (ll i=2;i<=t;i++){
    18          if (!bo[i]) primer[++ns]=i;
    19          for (ll j=1;j<=ns && i*primer[j]<=t;j++){
    20              bo[i*primer[j]]=1;
    21              if (i%primer[j]==0) break;
    22          }
    23      }
    24 }
    25 int main(){
    26     freopen("bz1300.in","r",stdin);
    27     freopen("bz1300.out","w",stdout);
    28     ll i,j;
    29     scanf("%I64d%I64d
    ",&n,&m);
    30     makepr(n);
    31     for (i=1;i<=ns;i++){
    32         for (j=primer[i];j<=n;j*=primer[i]) sum[i]+=n/j;
    33         for (j=primer[i];j<=m;j*=primer[i]) sum[i]-=m/j;
    34         for (j=primer[i];j<=n-m;j*=primer[i]) sum[i]-=(n-m)/j;
    35     }
    36     for (i=1;i<=ns;i++)
    37     if (sum[i]){
    38                 ans=(ans*power(primer[i],sum[i]))%mo;
    39                 save+=log10(primer[i])*sum[i];
    40     }
    41     if (save<12) printf("%I64d",ans);
    42     else{
    43          long double ans2=pow(10,save-static_cast<int>(std::floor(save))+2);
    44          printf("%I64d...%I64d",static_cast<ll>(floor(ans2)),ans%(mo/1000));
    45     }
    46     fclose(stdin);
    47     fclose(stdout);
    48 } 
    View Code

  • 相关阅读:
    使用requests爬虫简单获取知乎问题信息
    slam介绍
    move_base 控制机器人(2)
    move_base 控制机器人(1)
    Linux 常用命令-touch
    Linux 常用命令-rmdir
    Linux 常用命令-rm
    Linux 常用命令-mkdir
    Linux 目录结构
    Linux 常用命令-pwd
  • 原文地址:https://www.cnblogs.com/g-word/p/3377953.html
Copyright © 2011-2022 走看看