LightOJ1282 Leading and Trailing 數學性質


LightOJ1282 Leading and Trailing


標籤

  • 數學性質
  • 前導和後導的求法

前言


簡明題意

  • 給定n,k(n<=max_int,k<=1e7),求nkn^k的前3位和後三位。

思路

  • 首先後三位很好求,快速冪對1000取模就好了。重點在如何求前三位。
  • 有這樣一個性質:10k10^k,假設k的整數部分和小數部分分別是a和b,那麼10a10^a指定了這個數的位數,而10b10^b指定了實際的數(但是縮小到了10以內)。所以說,對於數n,我們直接求出log10nlog_{10}n的小數部分b,然後計算10b10^b就是原數縮小到10以內的數,這個時候給他乘100然後取整數部分,就是前導了。
  • 但是實際要求的不是n的前導,而是nkn^k的前導。n=10kna=10akn=10^k,n^a=10^{ak},所以其實在計算完對數後多乘一下就好了。

注意事項


總結

  • 10k=10a+10b10^k=10^a+10^b,其中10a10^a指定位數,10b10^b指定大小
  • 如何取一個數的小數部分?用fmod,fmod用於小數取餘,那麼n對1取餘得到的就是小數部分了。
  • 用setfill設定填充字符,用setw設定長度。他倆都在iomanip裏

AC代碼

#include<cstdio>
#include<cmath>
#include<iostream>
#include<iomanip>
using namespace std;

const int mod = 1000;

int ksm(int a, int b)
{
	int ans = 1, base = a;
	while (b)
	{
		if (b & 1)
			ans = 1ll * ans * base % mod;
		b >>= 1;
		base = 1ll * base * base % mod;
	}
	return ans;
}

void solve()
{
	int t;
	scanf("%d", &t);
	for (int i = 1; i <= t; i++)
	{
		int n, k;
		scanf("%d%d", &n, &k);

		int x = (int)(powf(10, fmod(k * log10(n), 1)) * 100);
		while (x < 100) x *= 10;

		printf("Case %d: %d ", i, x);
		cout << setfill('0') << setw(3) << ksm(n, k) << endl;
	}
}

int main()
{
	freopen("Testin.txt", "r", stdin);
	solve();
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章