HDU1060 n^n求首位


0)

       题意:t个测试案例,每一次输入n,求n^n的第一位数是几。(1<=n<=1,000,000,000)


       分析:刚开始用大数模板,结果n>100,输出n^n时就已经在输出窗口连续输出了三行数字,10^9规模的n肯定不行;之后一直没做出来,比赛完看解题报告get到,大数是可以利用log来做以下转化,转化为10的幂的形式,进而分成10的整数部分×10的小数部分,从而方便得到首位数字,分析如下,耐心看完会发现很简单

m=n^n  

        log(10) m= log(10) n^n  //两边分别求对10的对数

        m=n^n=10 ^ (log(10) n^n) = 10 ^(n×log(10)n)  

        而此时的指数部分 n×log(10)n 可以化为(整数部分+小数部分)

        m= 10 ^(n×log(10)n) = 10 ^(decimal + integer)  = (10^decimal) ×  (10^integer) //decimal 小数的,integer整数的

        而10^integer的首位数是1,所以m的首位应该是由10^decimal 的首位决定的,而decimal<1,所以 (10^decimal )<10,所以直接输出10^decimal即可。那么怎样将一个数的整数部分和小数部分分开呢,自己实现应该不难,但有现成的函数可以调用,<math.h>下的modf函数,

       小数部分=modf(该数,&整数部分),注意 三个参数都用double类型。

       double x,decimal,integer;
       decimal=modf(x,&integer);
       printf("数x分解成小数与整数之和,分解后:小数部分是%lf,整数部分是%lf",decimal,integer);
       //大数计算中,我们需要注意中间的值是否会溢出,在下面的代码中,最大的中间的值应当是k*1.0*log10(k*1.0),1<k<10^9,0<log10(k)<9,所以0 <  k*1.0*log10(k*1.0)< 9 × (10^9), 而double 范围是16位数字(包括小数,且默认拿出6位做小数的有效数字位数),如果全是整数则有16位有效数字,所以并没有超出double的表示范围,不会溢出。(而对程序的检测也的确如此,输入题目要求的10^9返回了正常值,输入10^15,这一步应当是(15*(10^15) ) ,大于10^15,返回了异常值。

1)

#include<stdio.h>
#include<math.h>
int main()
{
	int t;
	scanf("%d",&t);
	int k;
	while(t--){
		scanf("%d",&k);
		double decimal,integer;//小数部分,整数部分
		decimal=modf(k*1.0*log10(k*1.0),&integer); //乘1.0变double类型
		printf("%d\n",(int)pow(10,decimal));
	}
}


2)

Description

Given a positive integer N, you should output the leftmost digit of N^N. 
 

Input

The input contains several test cases. The first line of the input is a single integer T which is the number of test cases. T test cases follow. 
Each test case contains a single positive integer N(1<=N<=1,000,000,000). 
 

Output

For each test case, you should output the leftmost digit of N^N. 
 

Sample Input

    
    
2 3 4
 

Sample Output

    
    
2 2

Hint

 In the first case, 3 * 3 * 3 = 27, so the leftmost digit is 2. In the second case, 4 * 4 * 4 * 4 = 256, so the leftmost digit is 2. 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,关于 HDU4992 所有原根的问题,我可以给出以下解答: 1. 首先,我们需要知道什么是原根。原根是指模 n 意义下,所有与 n 互质的数 a 的最小正整数 k 次幂对 n 取模的值覆盖了所有与 n 互质的数。简单来说,就是如果一个数 a 是模 n 意义下的原根,那么 a 的任何正整数次幂对 n 取模的值都不相同,且能覆盖所有与 n 互质的数。 2. 为了模 n 意义下的所有原根,我们需要先出与 n 互质的数的个数 phi(n)。phi(n) 可以使用欧拉函数出。 3. 然后,我们需要枚举模 n 意义下的所有数,判断它是否是原根。具体来说,对于每个 a,我们需要判断 a 的每个小于 phi(n) 的正整数次幂对 n 取模的值是否都不相同,且能覆盖所有与 n 互质的数。如果是,那么 a 就是模 n 意义下的原根。 4. 代码实现可以参考以下 Java 代码: ``` import java.util.*; public class Main { static int gcd(int a, int b) { return b == 0 ? a : gcd(b, a % b); } static int phi(int n) { int res = n; for (int i = 2; i * i <= n; i++) { if (n % i == 0) { res = res / i * (i - 1); while (n % i == 0) { n /= i; } } } if (n > 1) { res = res / n * (n - 1); } return res; } static int pow(int a, int b, int mod) { int res = 1; while (b > 0) { if ((b & 1) != 0) { res = res * a % mod; } a = a * a % mod; b >>= 1; } return res; } static boolean check(int a, int n, int phi) { for (int i = 1, j = pow(a, i, n); i <= phi; i++, j = j * a % n) { if (j == 1) { return false; } } return true; } public static void main(String[] args) { Scanner scanner = new Scanner(System.in); while (scanner.hasNext()) { int n = scanner.nextInt(); int phi = phi(n); List<Integer> ans = new ArrayList<>(); for (int i = 1; i < n; i++) { if (gcd(i, n) == 1 && check(i, n, phi)) { ans.add(i); } } Collections.sort(ans); for (int x : ans) { System.out.print(x + " "); } System.out.println(); } } } ``` 其中,gcd 函数用于最大公约数,phi 函数用于欧拉函数,pow 函数用于快速幂模,check 函数用于判断一个数是否是原根。在主函数中,我们依次读入每个 n,出 phi(n),然后枚举模 n 意义下的所有数,判断它是否是原根,将所有原根存入一个 List 中,最后排序输出即可。 希望我的回答能够帮到你,如果你有任何问题,欢迎随时提出。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值