【浙大第19届校赛:B】Even Number Theory (数论+大数)

有数学符号图片,复制不过来,所以只能附上原题地址

题目地址:http://acm.zju.edu.cn/onlinejudge/showContestProblem.do?problemId=5970

题意:给出了三个新定义

  1. E-prime : ∀ num ∈ E,不存在两个偶数a,b,使得 num=a*b;(简言之,num的一对因子不能全为偶数)
  2. E-prime factorization : 定义集合P由 E-prime 元素组成,定义 e = p1*p2*.....*pn;(p1,p2,....,pn ∈ P , |P| = n)
  3. E-factorial : 定义 e!! = 2*4*6*8*.........*e;(简言之,偶数e及其之前的偶数连乘积)

  输出一个数 e ,求满足条件2的集合P,并且集合P需满足:p1*p2*.....*pn = e!! , |P| = n;

  求 n 的最大值;

题解:

别看定义了一堆东西,实际上就是给你一个偶数,先算出他的偶阶乘(比如给你一个12,偶阶乘就是2×4×6×8×10×12)

然后求出这个阶乘最多可以由多少个偶数相乘得到

因为这个阶乘是用偶数乘起来的,想要个数最多,肯定是用2乘,所有就求一下一共含有多少2就可以了,奇数可以不考虑

因为如果有奇数,那就用2乘上它让它变成偶数就ok了
因为输入的数据非常大,题目范围是1e10000,所以要用大数字处理。

反思:

写的时候题目没完全理解,想成求多少个因子为“2”,其实方向对了,可是做法却一直推规律,结果最后也没搞定,大佬一句1e10000就是2的3000多次方就点出题解了,可是自己还没想到,真的菜

代码:

python

t = int(input())
while t > 0:
    n = int(input())
    ans = int(0)
    t -= 1
    while n > 0:
        n //= 2
        ans += n
    print(ans)

java大数

import java.math.BigInteger;
import java.util.Scanner;
 
public class Main {
 
	public static void main(String[] args) {
		
		Scanner sc = new Scanner(System.in);
		int t;
		t = sc.nextInt();
		while(t -- > 0){
			BigInteger n = null;
			n = sc.nextBigInteger();
			BigInteger x = new BigInteger("2");
			BigInteger p = new BigInteger("0");
			BigInteger sum = new BigInteger("0");
			while(n.compareTo(p) != 0)
			{
				sum = sum.add(n.divide(x));
				n = n.divide(x);				
			}
			System.out.println(sum);
		}
	}
 
}

c++

#include<iostream>
#include<cstdio>
using namespace std;
#define BigInteger long long

BigInteger e;
BigInteger base;

BigInteger F()
{
    BigInteger curBase=2;
    BigInteger ans=0;
    BigInteger l=base/curBase;
    BigInteger r=e/curBase;
    for(int i=1;i < 4000;++i)
    {
//        cout<<l<<' '<<r<<endl;
        if(l >= r)
            break;
        BigInteger tmp=(r-l)/2;
        if(r&1)
            tmp++;
        ans=ans+tmp*i;
        l=l/2;
        r=r/2;
    }
    return ans;
}
void Solve()
{
    base=1;
    while(base*2 <= e)
        base *= 2;
    BigInteger ans=base-1;

    if(base != e)
        ans=ans+F();

    cout<<ans<<endl;
}
int main()
{
    int test;
    while(cin>>test)
    {
        while(test--)
        {
            cin>>e;
            Solve();
        }
    }
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值