「考试」num (破800纪念)

Posted lrefrain

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了「考试」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!)=\fracn!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,\fraci5)\prod \limits_i=1,5\perp i^nExt(5,i)(mod\ 5)$

$\equiv Ext(5,\fracn!5)\prod \limits_i=1,5\perp i^ni(mod\ 5)$

$\equiv Ext(5,\fracn!5)(\prod \limits_i=1,5\perp i^5i)^\fracn5 \prod \limits_i=1,5\perp 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

 

以上是关于「考试」num (破800纪念)的主要内容,如果未能解决你的问题,请参考以下文章

系统分析师考试

CKA 考试心得

#10.6考试总结

RHCSA(7.0)考试解析

AWS 考试认证心得(SAA)(下)

考试系统随机出题处理逻辑