阶乘的约数和
问题描述
给定你一个正整数 nn,你需要求出 n!n! 的约数之和,结果对 998244353998244353 取模。
n!n!:nn 的阶乘,含义为 1×2×3×...×n1×2×3×...×n。
输入格式
输入包含一个正整数 nn。
输出格式
输出 n!n! 的约数之和,对 998244353998244353 取模。
样例输入
20
样例输出
843703748
评测数据规模
1≤n≤2×1051≤n≤2×105。

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class Main {
static int N = 2*100010,mod=998244353,ind;
static int prime[]=new int[N];
static int a[]=new int[N];
static boolean f[]=new boolean[N];
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int n=Integer.parseInt(br.readLine());
// String g[] = br.readLine().split(" ");
// int n=Integer.parseInt(g[0]);
get_Prime(n);//n的阶乘只能分解出n以内的质数
int nn=n;
for (int i = 0; i < ind; i++) {
while(n/prime[i]>0){
n=n/prime[i];
a[i]+=n;
}
n=nn;
}
long res=1;
//每个p的多项式可以用等比数列的和求出,这里有除法取模 所以必须用逆元
for (int i = 0; i < ind; i++) {
res=(res*(reverseInfo(prime[i], a[i]+1)-1)%mod*reverseInfo(prime[i]-1,mod-2)%mod);
}
System.out.println(res);
}
static long reverseInfo(long a,int p){
long res=1;
while(p>0){
if((p&1)==1){
res=res*a%mod;
}
a=a*a%mod;
p=p>>1;
}
return res%mod;
}
static void get_Prime(int n){
for (int i = 2; i <= n; i++) {
if(!f[i])prime[ind++]=i;
for (int j = 0; j < ind && i*prime[j]<=n; j++) {
f[i*prime[j]]=true;
if(i%prime[j]==0)break;
}
}
}
}
斐波那契数列
斐波那契数列
题目描述
斐波那契数列:{F(1)=F(2)=1F(n)=F(n−1)+F(n−2)n>2,n∈N∗{F(1)=F(2)=1F(n)=F(n−1)+F(n−2)n>2,n∈N∗
给定一个正整数 NN,求F(N)F(N)在模 109+7109+7 下的值。
输入描述
第 11 行为一个整数 TT,表示测试数据数量。
接下来的 TT 行每行包含一个正整数 NN。
1≤T≤1041≤T≤104,1≤N≤10181≤N≤1018。
输出描述
输出共 TT 行,每行包含一个整数,表示答案。
输入输出样例
示例 1
输入
6
1
2
3
4
5
1000000000
输出
1 1 2 3 5 21

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class Main {
static int N = 2*100010,mod=(int)1e9+7,ind;
// static int prime[]=new int[N];
// static int a[]=new int[N];
// static boolean f[]=new boolean[N];
static long right[][]=new long[1][2];
static long left[][]={{1,1}};
static long a[][]={{1,1},{1,0}};
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int t=Integer.parseInt(br.readLine());
// String g[] = br.readLine().split(" ");
// int n=Integer.parseInt(g[0]);
for (int i = 0; i < t; i++) {
long n=Long.parseLong(br.readLine());
long aa[][] = matrixQuickMi(a,n-2);
System.out.println((aa[0][0]+aa[1][0])%mod);
}
}
static long[][] matrixQuickMi(long a[][],long p){
long res[][]={{1,0},{0,1}};
while(p>0){
if((p&1)==1){
res=multiple(res,a);
}
p=p>>1;
a=multiple(a,a);
}
return res;
}
static long[][] multiple(long a[][],long b[][]){
long res[][]=new long[2][2];
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 2; j++) {
for (int j2 = 0; j2 < 2; j2++) {
res[i][j]=(long)(res[i][j]+a[i][j2]*b[j2][j])%mod;
}
}
}
return res;
}
}
数列区间最大值
输入一串数字,给你 M 个询问,每次询问就给你两个数字 X,Y,要求你说出 X 到 Y 这段区间内的最大数。
输入格式
第一行两个整数 N,M 表示数字的个数和要询问的次数;
接下来一行为 N 个数;
接下来 M 行,每行都有两个整数 X,Y。
输出格式
输出共 M 行,每行输出一个数。
数据范围
1≤N≤105,
1≤M≤106,
1≤X≤Y≤N,
数列中的数字均不超过231−1
输入样例:
10 2
3 2 4 5 6 8 1 2 9 7
1 4
3 8
输出样例:
5
8


import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
public class Main {
static int N = 100010,M=(int)(Math.log(N)/Math.log(2)+1);
static int lg2[]=new int[N];
static int a[]=new int[N];
static int f[][]=new int[N][M];//表示以i为起点 长度为2^j的区间内的最大值
static BufferedWriter bw =new BufferedWriter(new OutputStreamWriter(System.out));
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
//int t=Integer.parseInt(br.readLine());
String g[] = br.readLine().split(" ");
int n=Integer.parseInt(g[0]),m=Integer.parseInt(g[1]);
g = br.readLine().split(" ");
for (int i = 1; i <= n; i++) {
a[i]=Integer.parseInt(g[i-1]);
}
lg2[1]=0;
for (int i = 2; i <= n; i++) {
lg2[i]=lg2[i/2]+1;
}
//f[i][j]=max(f[i][j-1],f[i+2^(j-1)][j-1]
//f[i][j]=ai
for (int j = 0; j <= lg2[n]; j++) {
for (int i = 1;i + (1<<j) - 1<= n; i++) {
//区间为[i,i+2^(j-1)-1]
if(j==0)f[i][0]=a[i];
else f[i][j]=Math.max(f[i][j-1],f[i+(1<<(j-1))][j-1]);
}
}
for (int i = 1; i <= m; i++) {
g = br.readLine().split(" ");
int l=Integer.parseInt(g[0]),r=Integer.parseInt(g[1]);
query(l,r);
}
}
static void query(int l,int r) throws IOException{
int len=r-l+1;
int k=lg2[len];
//第一个区间[l,l+(1<<k)-1] 第二个个区间[r-(1<<k)+1,r]
//两个区间有重叠 也可以
int res=Math.max(f[l][k], f[r-(1<<k)+1][k]);
bw.write(res+"\n");
bw.flush();
}
}