• 「考试」num (破800纪念)


    是第800题啦。

    怎么说,$rvalue$学长写的已经挺好的了,我在这里做一点补充,写一点理解。

    但是这道题真的值得写一下题解,毕竟一百行也算是数论工程题了。

    定义函数

    $Fp(k,n)$为$n$中$k$的最大幂次。

    $Ext(k,n)=n/Fp(k,n)$

    我们要求的就是$Ext(10,n!)%1000$

    怎么做。

    首先$Ext$函数在$k$为质数的情况下是完全积性函数。(这里zsq学长出锅了,没有说k是质数)

    这个证都不用证吧。。。根据定义直接出了。

    好到这步我都懂,甚至看到最后我都懂。

    可是根本想不到。

    这一步就是切入题目的最关键点了。

    为什么要设立这样一个函数。

    其实目的就是转化问题,本来让人摸不着头脑的题一下子思路就清晰起来了。

    可能这就是公式思想。把不会的转化为公式,然后用数学方法死刚公式就行了。

    然而$10$不是质数,不是很好求,所以我们用$CRT$合并对$Ext(10,n!)$求解。

    代出两个互质部分的式子。

    $Ext(10,n!)=frac{n!}{2^{Fp(5,n!)}5^{Fp(5,n!)}}$

    一种经典的$O(log_5(n))$阶乘求因子方法,可以很快的求出$Fp(5,n!)$,$2^c$和$5^c$互质,可以直接欧拉定理求逆元。

    所以其实求$Ext(5,n!)$即可。

    在$K==1$的时候。我们将$10$拆分成$2$和$5$。

    利用$Ext$的完全积性。

    $Ext(5,n!) equiv prod limits_{i=1}^{n!}Ext(5,i)(mod 5)$

    $equiv prod limits_{i=1,5|i}^{n!}Ext(5,frac{i}{5})prod limits_{i=1,5perp i}^{n}Ext(5,i)(mod 5)$

    $equiv Ext(5,frac{n!}{5})prod limits_{i=1,5perp i}^{n}i(mod 5)$

    $equiv Ext(5,frac{n!}{5})(prod limits_{i=1,5perp i}^{5}i)^{frac{n}{5}} prod limits_{i=1,5perp i}^{n\%5} i (mod 5)$

    发现是个递归式。

    一千的话,同理也可以快速递归的到答案。

    但是要写高精所以就很麻烦了。

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 using namespace std;
     5 const int maxn=1e2+5;
     6 typedef long long ll;
     7 inline void read(int &x)
     8 {
     9     x=0;char c=getchar();
    10     while(c<'0'||c>'9') c=getchar();
    11     while(c>='0'&&c<='9') x=(x<<1)+(x<<3)+c-48,c=getchar();
    12 }
    13 const int tw[4]={1,2,4,8},fi[4]={1,5,25,125},phif[4]={1,4,20,100},mo[4]={1,10,100,1000};
    14 int T,K,tc,fr,se,num;
    15 char s[maxn];
    16 int add(int x,int y,int mod) {return x+y>=mod?x+y-mod:x+y;}
    17 int mul(int x,int y,int mod) {return 1LL*x*y%mod;}
    18 int qw(int a,int b,int mod)
    19 {
    20     int ans=1;
    21     for(;b;b>>=1,a=mul(a,a,mod)) if(b&1) ans=mul(ans,a,mod);
    22     return ans;
    23 }
    24 struct Bigdata{
    25     int a[maxn];
    26     bool isz() {return a[0]==1&&a[a[0]]==0;}
    27     void init(char *s)
    28     {
    29         memset(a,0,sizeof(a));
    30         a[0]=strlen(s+1);
    31         for(int i=a[0];i>=1;--i) a[i]=s[a[0]-i+1]-48;
    32     }
    33     void divf(int m)
    34     {
    35         int x=0;
    36         for(int i=a[0];i>=1;--i) x=x*10+a[i],a[i]=x/m,x%=m;
    37         while(!a[a[0]]&&a[0]>1) --a[0];
    38     }
    39     int getm(int mod)
    40     {
    41         int res=0;
    42         for(int i=a[0];i>=1;--i) res=add(a[i],mul(res,10,mod),mod);
    43         return res;
    44     }
    45     int getn() {int res=0;for(int i=a[0];i>=1;--i) res=res*10+a[i];return res;}
    46     void print() {for(int i=1;i<=a[0];++i) printf("%d",a[i]);puts("");}
    47 }n,tmp;
    48 int nfac(Bigdata &t,int m,int mod)
    49 {
    50     int ans=0;
    51     while(!t.isz())
    52     {
    53         t.divf(m);
    54         ans=add(ans,t.getm(mod),mod);
    55     }
    56     return ans;
    57 }
    58 void lit(int n,int K)
    59 {
    60     const int mod=1e5;ll ans=1;
    61     for(int j=1,t=j;j<=n;++j,t=j)
    62     {
    63         while(!(t%10)) t/=10;t%=mod;ans*=t;
    64         while(!(ans%10)) ans/=10;ans%=mod;
    65     }
    66     for(int i=K;i>=1;--i) printf("%lld",(ans/mo[i-1])%10);puts("");
    67 }
    68 int Ext()
    69 {
    70     if(n.isz()) return 1;
    71     int up=n.getm(fi[K]);
    72     tmp=n;tmp.divf(fi[K]);n.divf(5);
    73     int tc=tmp.getm(phif[K]),t=1;
    74     for(int i=1;i<=up;++i) if(i%5) t=mul(t,i,fi[K]);
    75     return mul(mul(qw(num,tc,fi[K]),t,fi[K]),Ext(),fi[K]);
    76 }
    77 int main()
    78 {
    79 //    freopen("ex_num2.in","r",stdin);
    80 //    freopen("a.out","w",stdout);
    81     read(T);
    82     while(T--)
    83     {
    84         scanf("%s",s+1);n.init(s);read(K);
    85         if(n.a[0]<=2) {lit(n.getn(),K);continue;}
    86         tmp=n;
    87         tc=nfac(tmp,5,phif[K]);
    88         fr=qw(qw(2,tc,fi[K]),phif[K]-1,fi[K]);
    89         for(int i=num=1;i<=fi[K];++i) if(i%5) num=mul(num,i,fi[K]);
    90         se=Ext();
    91         se=mul(se,fr,fi[K]);
    92         while(se%tw[K]) se=add(se,fi[K],tw[K]*fi[K]);
    93         for(int i=K;i>=1;--i) printf("%d",(se/mo[i-1])%10);puts("");
    94     }
    95     return 0;
    96 }
    num

    最后$%%%zsq$学长,教我多项式,题解写的又好。

  • 相关阅读:
    element ui源码解析 -- button篇
    如何在vue项目中使用百度编辑器ueditor
    基于element ui的图片预览插件
    jquery weui日期选择控件添加取消按钮
    swiper如何实现轮播嵌套轮播
    jQuery weui Select组件显示指定值
    vue打包静态资源路径不正确的解决办法
    CSS垂直居中的实现
    vue学习笔记二:v-if和v-show的区别
    vue学习笔记一:用Key管理可复用元素
  • 原文地址:https://www.cnblogs.com/Lrefrain/p/11626541.html
Copyright © 2020-2023  润新知