【积累】【数学】关于log运算

有关log运算的二三题

1,hdu Leftmost Digit

题意:

给定正整数 \(n\) ,输出 \(n^n\) 的最高位上的数字。其中, \(1\leq n\leq1,000,000,000\)

解:

\[\begin{align*} n^n&=a.b\times10^k\\ lg(n^n)&=lg(a.b\times10^k)\\&=lg(a.b)+k\\ lg(n^n)-k&=lg(a.b)\\ a&=(int)10^{lg(n^n)-k} \end{align*} \]

代码:

#include<bits/stdc++.h>
using namespace std;

int main()
{
    int T,n;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d",&n);
        printf("%d\n",(int)pow(10,log10(n)*n-(ll)(log10(n)*n)));
    }
}

2,P1045 麦森数

题意:

对于给定整数 \(P\) ( \(1000< P< 3100000\) ) ,第一行输出十进制 \(2^P-1\) 的位数,第二行,输出十进制 \(2^P-1\) 的最后500位数字(每行输出50位,共输出10行,不足500位时高位补0)。

解:

对于输出位数:

首先要知道 \(2^P-1\)\(2^P\) 的对应十进制数的位数是相同的(因为 \(2^P\) 尾数不为 \(0\) )。

其次,对于一个数 \(10^n\) ,它的位数是 \(n+1\)

那么对于 \(k=2^P\) 有:

\[\begin{align*} k&=2^P\\&=(10^{log_{10}\,2})^P\\&=10^{P\,log_{10}\,2} \end{align*} \]

所以,\(2^P-1\) 的十进制位数等于 \(2^P\) 的十进制位数,等于 \(P\,log_{10}2+1\)

输出最后500位:高精或者java

代码:

import java.math.BigInteger;
import java.util.Scanner;

public class Main{
	static final int maxn=100005;
	static final BigInteger BI=null;
	static Scanner input=new Scanner(System.in);
	public static void main(String sssss[]) {
		int p=input.nextInt();
		BigInteger res=BI.valueOf(1);
		BigInteger mod=BI.valueOf(10);
        BigInteger x=mod.pow(50),y;
		int len=(int) (Math.log10(2)*p+1);
		mod=mod.pow(500);
		for(int i=1,j=0;i<=p;i++,j++) {
			res=res.multiply(BI.valueOf(2));
			if(j>5000){
                res=res.mod(mod);j=0;
            }
		}
        res=res.mod(mod);
		res=res.subtract(BI.ONE);
		System.out.println(len);
        for(int i=1;i<=10;i++){
            mod=mod.divide(x);
            y=res.divide(mod);
		    System.out.println(String.format("%050d", y));
            res=res.subtract(y.multiply(mod));
        }
	}
}

3,How Many Times?

题意:

初始有 \(n\) 个堆,第 \(i\) 堆有一个数 \(i\)

\(3\) 种操作:

  • 1 X Y :把包含数 \(X\) 和包含数 \(Y\) 的堆合并
  • 2 X :如果包含数 \(X\) 的堆存在,删除该堆里最大的那个数
  • 3 X Y :输出 \(\frac{max(S_x,S_y)}{min(S_x,S_y)}\) ,其中 \(S_x=1\times a_1\times a_2\times\dots\times a_{size_x}\)\(a_i\) 是堆 \(X\) 的第 \(i\) 个数。

且,如果输出的数大于 \(10,000,000,000,000,000\) ,则输出 \(10,000,000,000,000,000\)

输出数据与标准数据的差不能超过 \(10^{-6}\)

解:

启发式合并。

对于高精度的运算,用浮点数的对数加法运算代替。

\[\frac{a_1\times a_2\times\dots\times a_{size_x}}{b_1\times b_2\times\dots\times b_{size_y}}=10^{lg \frac{a_1\times a_2\times\dots\times a_{size_x}}{b_1\times b_2\times\dots\times b_{size_y}}} \]

\[\begin{align*} \\ lg \frac{a_1\times a_2\times\dots\times a_{size_x}}{b_1\times b_2\times\dots\times b_{size_y}}&=lg(a_1\times a_2\times\dots\times a_{size_x})-lg(b_1\times b_2\times\dots\times b_{size_y})\\&=(lg\,a_1+lg\,a_2+\dots+lg\,a_{size_x})-(lg\,b_1+lg\,b_2+\dots+lg\,b_{size_y}) \end{align*} \]

代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const double ep=1e-8;
const int mod=998244353;
const int inf=0x3f3f3f3f;
const int maxn=1e5+5;
 
priority_queue<int>que[maxn];
double val[maxn];
int fa[maxn];
int main()
{
    int n,m,op,x,y;
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++){
        que[i].push(i);
        fa[i]=i;
        val[i]=log10(i);
    }
    while(m--)
    {
        scanf("%d",&op);
        if(op==1){
            scanf("%d%d",&x,&y);
            x=fa[x];
            y=fa[y];
            if(!x||!y||x==y)continue;
            if(que[x].size()<que[y].size())swap(x,y);
            val[x]+=val[y];val[y]=0;
            while(!que[y].empty()){
                que[x].push(que[y].top());
                fa[que[y].top()]=x;
                que[y].pop();
            }
            que[y]=priority_queue<int>();
        }else if(op==2){
            scanf("%d",&x);
            x=fa[x];
            if(!x)continue;
            val[x]-=log10(que[x].top());
            fa[que[x].top()]=0;
            que[x].pop();
        }else{
            scanf("%d%d",&x,&y);
            x=fa[x];y=fa[y];
            printf("%.6f\n",pow(10,min(fabs(val[x]-val[y]),16.0)));
        }
    }
}
posted @ 2020-12-08 21:03  草丛怪  阅读(549)  评论(0编辑  收藏  举报