【计数】字典序问题和最多约数问题

本文提供了两个Java实现的算法题目解答,第一个题目通过组合数学的方法计算字符串的排名,第二个题目涉及质数判断及约数计数,利用链表提高查找效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

import java.util.Scanner;

public class Main {

	public static void main(String[] args) {
		int n,len;
		String c;
		//读入n
		Scanner sn=new Scanner(System.in);
		n=sn.nextInt();

		for(int i=0;i<n;i++)
		{
			int sum=1;//用来存放这个串是多少号,1表示它自己占了1号,后续只要加上前面的号
			//读入串
			Scanner sc=new Scanner(System.in);
			c=sc.next();

			len=c.length();
			
			for(int j=1;j<len;j++)
				sum+=Cfun(26,j);//对小于len长度的所有串都要加进来
			
			//对于len长度的串
			int[] CtoI=new int[len];
			for(int j=0;j<len;j++)//先对每一位的字符变成从a开始的编号
				CtoI[j]=(int)(c.charAt(j)-'a'+1);//存进来
			
			//初始化'这一位的前一个字母编号'是0(0表示没有,1表示'a'...)
			int pre=0;
			//对于len长度的每一位
			for(int j=0;j<len;j++)
			{
				int much=CtoI[j]-pre-1;//计算它和前一个字母之间有多少字母
				//对这之中的每个字母,合法的情况有C(26-字母编号,剩余长度len-j-1)种
				for(int k=pre+1;k<pre+1+much;k++)//k为这之中的每个字母编号
				{
					sum+=Cfun(26-k,len-j-1);//把此位置是该字母时的合法情况加进来
				}
				pre=CtoI[j];//更新pre(下一次循环时的'前一个字母编号'就是本次的字母编号)
			}
			
			System.out.println(sum);
		}
	}

	//求C(m,n)
	public static int Cfun(int m,int n){
		int AnN=1,AmN=1;
		for(int i=1;i<=n;i++)
			AnN*=i;
		for(int i=m;i>m-n;i--)
			AmN*=i;
		return AmN/AnN;
	}
}

 

 

 

 

 

import java.util.LinkedList;
import java.util.Scanner;

public class Main {

	public static void main(String[] args) {
		int a,b;
		int ok=2;//ok表示当前达到的最大的b,用于考察是否要更新质数(链)表
		int j;
		int num,max,index;
		Scanner s=new Scanner(System.in);
		//建立一个存质数的链表(加快add的速度)
		LinkedList<Integer> LL=new LinkedList<Integer>();
		while(s.hasNext())
		{
			max=index=0;//初始化max=index=0
			a=s.nextInt();
			b=s.nextInt();
			if(b>ok)//这时需要更新List
			{
				for(int i=ok;i<b;i++)
				{
					for(j=2;j*j<=i;j++)
						if(i%j==0)//i不是质数
							break;
					if(j*j>i)//i是质数
						LL.add(i);
				}
				ok=b;//更新ok的值为新的b
			}
			
			//如果为空,那么就输出b
			if(LL.isEmpty()==true)
			{
				System.out.println("本次找到"+b+",约数太少了");
				continue;
			}
			
			//否则
			for(int i=a;i<=b;i++)
			{
				num=1;//每次都初始化num=1,因为后面要作乘法
				for(Integer k:LL)
				{
					if(i<k)//优化
						break;
					
					if(i%k==0)//如果k是i的一个质因数
					{
						//从质因数的0次方(即不取它)到N次方共N+1种可能性
						num*=(NumFun(i,k)+1);
					}
				}
				
				if(num>max)//出现更大的就更新
				{
					max=num;
					index=i;
				}
			}
			
			System.out.println("本次找到"+index+"有"+max+"个约数");
		}//end while
	}//end main()
	
	//该函数求n里有多少个m
	public static int NumFun(int n,int m){
		int sum=0;
		while(n%m==0)
		{
			n/=m;
			sum++;
		}
		return sum;
	}
	
}

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值