2019 ICPC南昌邀请赛网络赛部分题解

A.

题目:https://nanti.jisuanke.com/t/38220

题意:求前5个因子和等于它本身的数(不算自身)

   线性筛

#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;

const int N = 4e6 + 100;

int prime[N], f[N], fu[N], tot;
bool is_prime[N];

void init() {
	memset(is_prime, true , sizeof(is_prime));
	for (int i = 2; i < N; i++) {
		if (is_prime[i]) {
			prime[tot++] = i;
			f[i] = 1 + i;
			fu[i] = i;
		}
		for (int j = 0; j < tot && i * prime[j] < N; j++) {
			is_prime[i * prime[j]] = false;
			if (i % prime[j] == 0) {
				fu[i * prime[j]] = fu[i] * prime[j];
				if (fu[i] == i) {
					f[i * prime[j]] = f[i] + i * prime[j];
				}else {
					f[i * prime[j]] = f[i / fu[i]] * f[fu[i] * prime[j]];
				}
				break;
			}else {
				fu[i * prime[j]] = prime[j];
				f[i * prime[j]] = f[i] * f[prime[j]];
			}
		}
		if (f[i] == i * 2)
			printf("%d\n", i);
	}
}

int main() {
	puts("6");
    puts("28");
    puts("496");
    puts("8128");
    puts("33550336");
	return 0;
}

C.

题目:https://nanti.jisuanke.com/t/38222

题意:f(x)是斐波那契数的第x项,g(x)=f(f(x)),对于给定的n,将其表示成若干个g数的和,要求字典序最小,n<10^100000

矩阵快速幂求一下f(x),预处理前29项g(x)。

可以发现g(x)的增长速度非常快,其实在第29项就已经超出10^100000,由于后面的项差过大,所以方法基本唯一,所以就把贪心选一下,然后前几项在特判一下取个最小字典序就ok了。

import java.io.*;
import java.math.*;
import java.util.*;
public class Main
{
	static int maxn = 29;
	static BigInteger []w = new BigInteger[maxn];
	static int []v = new int[maxn];
 	public static BigInteger f(BigInteger n){
 		n = n.subtract(BigInteger.ONE);
		BigInteger [][]a = new BigInteger[2][2];
		BigInteger [][]b = new BigInteger[2][2];
		BigInteger [][]c = new BigInteger[2][2];
		for(int i = 0; i < 2; i++) for(int j = 0; j < 2; j++) a[i][j] = BigInteger.ZERO;
		a[0][0] = a[1][0] = a[0][1] = BigInteger.ONE; 
		for(int i = 0; i < 2; i++) for(int j = 0; j < 2; j++) b[i][j] = BigInteger.ZERO;
		for(int i = 0; i < 2; i++) b[i][i] = BigInteger.ONE;
		while(n.compareTo(BigInteger.ZERO) > 0){
			if(n.mod(new BigInteger("2")).equals(BigInteger.ONE)){
				for(int i = 0; i < 2; i++){
					for(int j = 0; j < 2; j++){
						c[i][j] = BigInteger.ZERO;
						for(int k = 0; k < 2; k++){
							c[i][j] = c[i][j].add(b[i][k].multiply(a[k][j]));
						}
					}
				}
				for(int i = 0; i < 2; i++){
					for(int j = 0; j < 2; j++){
						b[i][j] = c[i][j];
					}
				}
			}
			for(int i = 0; i < 2; i++){
				for(int j = 0; j < 2; j++){
					c[i][j] = BigInteger.ZERO;
					for(int k = 0; k < 2; k++){
						c[i][j] = c[i][j].add(a[i][k].multiply(a[k][j]));
					}
				}
			}
			for(int i = 0; i < 2; i++){
				for(int j = 0; j < 2; j++){
					a[i][j] = c[i][j];
				}
			}
			n = n.divide(new BigInteger("2"));
		}
		//System.out.println("len " + b[0][0].toString().length());
		return b[0][0];
	}
    public static void main(String[] args)
    {
        Scanner cin = new Scanner (System.in);
        for(int i = 1; i < maxn; i++){
        	w[i] = f(f(BigInteger.valueOf(i)));
        }
       // System.out.println(w[6] + " " + w[7]);
        int T = cin.nextInt();
        while(T > 0){
        	T--;
        	BigInteger n = cin.nextBigInteger();
        	int tot = 0;
        	for(int i = maxn - 1; i > 0; i--){
        		if(n.equals(new BigInteger("5")) && i >= 4){
        			v[tot++] = 4;
        			v[tot++] = 3;
        			v[tot++] = 2;
        			v[tot++] = 1;
        			n = BigInteger.ZERO;
        			break;
        		}
        		if(n.equals(new BigInteger("4")) && i >= 4){
        			v[tot++] = 4;
        			v[tot++] = 2;
        			v[tot++] = 1;
        			n = BigInteger.ZERO;
        			break;
        		}
        		if(n.equals(new BigInteger("3")) && i >= 3){
        			v[tot++] = 3;
        			v[tot++] = 2;
        			v[tot++] = 1;
        			n = BigInteger.ZERO;
        			break;
        		}
        		if(n.equals(new BigInteger("2")) && i >= 2){
        			v[tot++] = 2;
        			v[tot++] = 1;
        			n = BigInteger.ZERO;
        			break;
        		}
        		if(n.equals(new BigInteger("1")) && i >= 1){
        			v[tot++] = 1;
        			n = BigInteger.ZERO;
        			break;
        		}
        		if(n.compareTo(w[i]) >= 0){
        			v[tot++] = i;
        			n = n.subtract(w[i]);
        		}
        	}
        	if(!n.equals(BigInteger.ZERO)) System.out.println(-1);
        	else{
        		for(int i = tot - 1; i >= 0; i--) System.out.printf("%d%c", v[i], i == 0 ? '\n' : ' ');
  
  • 6
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值