1. 程式人生 > >階乘問題 【數論】

階乘問題 【數論】

ring 所有 ios ans for 一行 base htm aps

題目來源

  洛谷1134   https://www.luogu.org/problemnew/show/P1134

題目簡述

   求 N!中最右側第一個非零項    (命名為有效位)

輸入輸出格式

  輸入格式:

  僅一行包含一個正整數 NN 。

  輸出格式:

  一個整數,表示最右邊的非零位的值。

分析

  對於任意 N>1

  有效位只能為 2,4,6,8

  觀察這幾個數之間的連系(我的著手點為2進制)

    2=2

    4=2x2

    8=2x2x2

    6=2x2x2x2 (有效位)

    2=2x2x2x2x2

    4=2x2x2x2x2x2

    ......

  那麽可以得到

    在這四個數中,

      任意數 x6 得到其本身

      任意數 x8 等價於減少一個 x2 (2=2x2x2x2x2)

  接著,對於所有存在的個位數字 (因為需要排除個位為零導致十位數字參與運算的幹擾,排除數字5,0)

      1x2x3x4x6x7x8x9=6 (72576有效位為6)

      而根據前文分析 ,x6是只會無意義的

  所以對於 10*(k+1)>N>10*k 時 (1~10*k) 的相乘是無意義的

      即我們只需要計算 N的個位相乘

  最後再看我們先前忽略的幹擾數字:

      0 無法帶來任何改變 ,忽略

      5 對於 2x2x2x..x2 的一個數來說 x5 等價於減少一個 x2 ,也就是說 x5 等價於 x8 (我們這麽做的目的是為了排除x5所導致對十位數字的計算)。而因為1~N中因數5的系數是連續的(例如N=32 具有1x5,2x5,3x5,4x5,5x5,6x5 共6(32/5)個5需要特殊處理,且其中系數1,2,3,4,5,6是連續且需要計算的,運算過程直接當成 N=6算即可)

技術分享圖片
 1 #include<queue>
 2 #include<cstdio>
 3 #include<cstring>
 4
#include<iostream> 5 #include<algorithm> 6 using namespace std; 7 int N; 8 void Read(int &x){ 9 x=0; 10 char c=getchar(); 11 while(!isdigit(c)) c=getchar(); 12 while(isdigit(c)) x=x*10-0+c,c=getchar(); 13 return ; 14 } 15 void Write(int x){ 16 int np=0; 17 int s[505]; 18 while(x) s[++np]=x%10,x/=10; 19 while(np) putchar(s[np--]+0); 20 putchar(\n); 21 return ; 22 } 23 int E[4]={6,8,4,2}; //乘8的有效位(以4為周期的數列) 24 int main(){ 25 Read(N); 26 int ans=1; 27 while(N){ 28 for(int i=1;i<=(N%10);i++) 29 if(i!=5) ans=(ans*i)%10; 30 N/=5; //計算特殊處理的5 和 這些5的系數 31 ans=(ans*E[N%4])%10; 32 } 33 Write(ans); 34 return 0; 35 }
CODE

      

    

  

階乘問題 【數論】