一、最大乘积
解析:
全排列进行运算,前置条件:乘积大于784316925;
不会全排列的可以看看下面的模板,链接中还有更多模板,好像有十来种?
全排列模板:Java【全排列 算法 模板】_山167的博客-CSDN博客_java全排列模板
public class Main {
public static void main(String[] args) {
int arr1[] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
int arr2[] = {1, 2, 3};
f(arr1, 0);
}
//确认某一个排列的第k位
private static void f(int[] arr, int k) {
if (k == arr.length) { //全部确认
/*
for(int x: arr) {
System.out.print(x);
}
System.out.println();
*/
//函数功能区
return;
}
for (int i = k; i < arr.length; i++) { //选定第k位
//将第i位和第k位交换
int t = arr[i];
arr[i] = arr[k];
arr[k] = t;
// 移交下一层去确认k+1位
f(arr, k + 1);
//回溯(换回来)
t = arr[i];
arr[i] = arr[k];
arr[k] = t;
}
}
}
代码:
import java.util.*;
public class Main {
static long max=0;
static int arr[]= {1,2,3,4,5,6,7,8,9};
static int []brr=new int[10];
public static void main(String[] args) {
dfs(0);
System.out.print(max);
}
public static void dfs(int step) {//全排列
if(step==9) {
check();
return;
}
for(int i=step;i<arr.length;i++)
{
swap(i,step);
dfs(step+1);
swap(i,step);
}
}
public static void swap(int i,int j)
{
int t=arr[i];
arr[i]=arr[j];
arr[j]=t;
}
public static void check()
{
for(int i=0;i<=7;i++)
{
h(i);
}
}
public static void h(int step) {
int n1=1;
int sum=0;
for(int i=step;i>=0;i--)
{
sum+=arr[i]*n1;
n1=n1*10;
}
int n=1;
int sums=0;
for(int i=8;i>step;i--)
{
sums+=arr[i]*n;
n=n*10;
}
long count= (long) sum *sums;
if(max<count) {
if(pd(count)) {
max = count;
}
}
}
public static boolean pd(long s) {//判断乘积是否有1-9
Arrays.fill(brr,0);
while(s!=0) {
long k=s%10;
brr[Math.toIntExact(k)]++;
if(brr[Math.toIntExact(k)]==2||k==0)
return false;
s/=10;
}
return true;
}
}
二、阶乘约数
解析:
这题的话会用到一个叫《唯一分解定理》的知识
就是说:一个数可以分解为唯一的质数乘积
18=233;20=225;100=225*5;
然后去计算每一个不同质数的使用次数,每个质数+1后相乘
18:(1+1)*(2+1)=6,18有6个约数:1 2 3 6 9 18
100:(2+1)*(2+1)=9,100有9个约数:1 2 4 5 10 20 25 50 100;
这题是100以内的阶乘,我们只需要求出每一个数所拥有的的质数的总使用个数即可
唯一分解定理:
代码:
import java.math.BigInteger;
public class Main {
public static void main(String[] args) {
int s;
int []arr=new int[101];
int []brr={2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97};
for (int i=2;i<=100;i++) {
s=i;
for (int j=0;j<25;j++){
if (s%brr[j]==0){
s/=brr[j];
arr[brr[j]]++;
j--;
}
}
}
BigInteger bi=new BigInteger(String.valueOf(1));
for (int i=2;i<=100;i++){
if (arr[i]!=0)
bi=bi.multiply(BigInteger.valueOf(arr[i]+1));
}
System.out.println(bi);
}
}
三、含2天数
解析:
时间问题,第一种枚举,一个一个循环判断,当然要注意平年和闰年(新手也能写系列)
第二种:java中有一个java.time.LocalDate;类,用这个可以直接提取时间,每一次为当前天数+1,判断是否存2即可;
Java的时间类:
代码:
import java.time.LocalDate;
public class Main {
public static LocalDate left=LocalDate.of(1900,1,1);
public static LocalDate right=LocalDate.of(9999,12,31);
public static void main(String[] args) {
int a,b,c;
long count=0;
while (right.compareTo(left)>=0){
a=left.getYear();
b=left.getMonthValue();
c=left.getDayOfMonth();
if (a%10==2||a/1000==2||a/10%10==2||a/100%10==2||b==2||b==12||c%10==2||c/10==2){
count++;
}
left=left.plusDays(1);
}
System.out.println(count);
}
}
四、K倍区间
解析:
用前缀和的方法把每一个位置和之前的位置求和,然后将每一个出现的数值统计
因为这题是k倍,所以我们可以把所有结果模k。那么最大求和数则为k-1,定义一个长度为k的数组足以存放对应数出现次数;
然后由后往前,查看该数前有多少个余数相同的求和数,则到达该数的有多少种不同的区间方案
前缀和+同余:
1 5 2 7 2
假设k=3;
1 6 8 15 17
arr[1]=1;arr[2]=6;arr[3]=8;arr[4]=15;arr[5]=17
对三取模后分别为 1 0 2 0 2
求出每一个余数出现的次数
0 : 2次
1 :1次
2 :2次
brr[0]=2,brr[1]=1;brr[2]=2;
arr[1]=1;arr[2]=0;arr[3]=2;arr[4]=0;arr[5]=2
从后往前计算出现多少次
arr[5]=2,要使为0 在它之前出现的2的次数,1次(brr[2]-1;
arr[4]为0,求它之前0的次数 1次(brr[0]-1;
arr[3]之前无2,arr[2]之前无0,arr[1]结束
次数是1+1+2(直接为0的次数)
代码:
import java.util.*;
import java.io.*;
public class Main{
static BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
static StreamTokenizer st=new StreamTokenizer(br);
public static void main(String []age) throws Exception{
int n=nextInt();
int k=nextInt();
int []arr=new int[n];
int []brr=new int [n+1];
int []crr=new int [k];
for(int i=0;i<n;i++){
arr[i]=nextInt();
brr[i+1]=(brr[i]+arr[i])%k;
crr[brr[i+1]]++;
}
long sum=crr[0];
for(int i=n;i>=1;i--){
crr[brr[i]]--;
if(crr[brr[i]]>0){
sum+=crr[brr[i]];
}
}
System.out.print(sum);
}
public static int nextInt() throws Exception{
st.nextToken();
return (int)st.nval;
}
}
版权归原作者 小怂很怂 所有, 如有侵权,请联系我们删除。