zerojudge d122. Oh! My Zero!!

 zerojudge d122. Oh! My Zero!!

千萬別用暴力解( 1a和2a的解法)!!,因為一定會TLE。
千萬別用2b!!,因為輸入很大(長整數),這樣字要用很大的記憶體,會出現錯誤(RE),我試過,真的。

解法大全:

1.依思路分:

a)直接算階乘

b)算5法


2.建表

a)建階乘表

b)建5表


千萬別用暴力解( 1a和2a的解法)!!,因為一定會TLE。
千萬別用2b!!,因為輸入很大(長整數),這樣字要用很大的記憶體,會出現錯誤(RE),我試過,真的。

思路:

數學歸納法

1.

首先,你要先了解10=2*5,且2出現的次數比5多

所以要算出現比較少的次數(5的次數)


2.

再來你得先寫兩個表格

分別為,

a)5的倍數數字的質因數中有多少的5(5的倍數數字可以整除幾次5)

用數學式表示:n=k*5^m (k,m為正整數)

b)輸入和輸出的關係


3.

找規律


我的解法:

先用這方式寫
2b)先建表(1~1000000中能被5整除的次數),在逐項加起來
#define PO 7
const int  MX=pow(10.0,PO);//because n is too large
// MX=pow(10.0,5);
typedef long long int LLI;
int five_n[MX]={0};

void print(int *,int );
void build()
{
	//memset(five_n,0,sizeof(five_n));
	for(int i=1;i<=PO;i++)
	{
		int n=pow(5.0,i);
		for(int  j=n;j<=MX;j+=n)
		{
			five_n[j]++;
		}		
	}
	return ;
}
int deal(LLI n)
{
	int sum=0;
	for(int i=5;i<=n;i+=5)
	{
		sum+=five_n[i];
	}	
	return sum;
}
RE (SIGSEGV) 


1b)算5法:就是輸入一個數字N,算N!可以被5除多少次

因為末位數是0或5的才能被5整除

因為N!=1*2*3*4*5*...*N

只要算1~N中末位數是0或5的數字可以被5整除的次數,加起來就是答案


但是我發現一個規律,5可以被5整除1次,10是1次,25是兩次

在1~N中有N/5個是5的倍數,有N/25個是25個倍數

ans=in/5+in/25+in/125+...

所以我可以化簡成:

                int ans=0;
		LLI n=1;
		for(int i=1;n<=in;i++)
		{
			n=pow(5.0,i);
			ans+=in/n;	
		}		
		cout<<ans<<endl;
//or
                int ans=0;
		LLI n=1;
		for(int i=1;n<=in;i++)
		{
			n*=5;
			ans+=in/n;	
		}		
		cout<<ans<<endl;
//AC (2ms, 312KB)

註:

因為這題比較難,所以有不懂的可以在下面留言

還有我沒寫所有的方法,若有新解法(請先測試),可以在下面留言

也要謝謝別人的解題報告,它提供我一些想法


Comments

Popular posts from this blog

zerojudge c561. Bert 愛搗蛋