【积累】【数学】关于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)));
}
}
}