是第800题啦。
怎么说,$rvalue$学长写的已经挺好的了,我在这里做一点补充,写一点理解。
但是这道题真的值得写一下题解,毕竟一百行也算是数论工程题了。
定义函数
$Fp(k,n)$为$n$中$k$的最大幂次。
$Ext(k,n)=n/Fp(k,n)$
我们要求的就是$Ext(10,n!)%1000$
怎么做。
首先$Ext$函数是完全积性函数。
这个证都不用证吧。。。根据定义直接出了。
好到这步我都懂,甚至看到最后我都懂。
可是根本想不到。
这一步就是切入题目的最关键点了。
为什么要设立这样一个函数。
其实目的就是转化问题,本来让人摸不着头脑的题一下子思路就清晰起来了。
可能这就是公式思想。把不会的转化为公式,然后用数学方法死刚公式就行了。
然而$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,5\perp i}^{n}Ext(5,i)(mod\ 5)$
$\equiv Ext(5,\frac{n}{5})\prod \limits_{i=1,5\perp i}^{n}i(mod\ 5)$
$\equiv Ext(5,\frac{n}{5})(\prod \limits_{i=1,5\perp i}^{5}i)^{\frac{n}{5}} \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