数学测试test20170304

【小Y的数学作业】(Homework.pas/c/cpp Time:1s Memory:256M)

【问题描述】

小Y是个很好学的孩子。(附注:Y=yang)
最近老师总是布置给他(或者她)一些数学作业题,每道作业题就是求一个数X与数字A的最大公约数和X与数字B的最小公倍数。这天晚上11:00,大黄到小Y家去“玩”,不小心弄翻了小Y的咖啡,结果N道题的数字X都看不见了,但是数字A、数字B与小Y算出来的答案都还在。小Y很急,想问你对于每一道数学作业题,到底有多少种X满足已经算出的答案。

【输入】

输入文件名为homework.in。
第一行一个整数N,代表数学老师布置的题目数量。
接下来N行,每行4个正整数A,A1,B,B1,代表Gcd(x,A)=A1,Lcm(x,B)=B1。

【输出】

输出文件名为homework.out
对于每个数学题,若存在这样的X,即输出合法的X的个数,否则输出0。

【输入输出样例】

Homework.in
2
41 1 96 288
95 1 37 1776

Homework.out

6
2

【数据范围】

对于50%的数据,保证有1≤A,A1,B,B1≤10000且n≤100。
对于100%的数据,保证有1≤A,A1,B,B1≤2,000,000,000且n≤2000。

【题解】

原题:NOIP2009第二题 Hankson 的趣味题 (传送门)

首先,如果B1无法整除A1,那么显然是无解的。
然后,对于某一个质因数P来说,假设A包含p的最高次幂为a,A1为b,B为c,B1为d,然后X包含p的最高次幂为x。
那么x必须满足如下条件: Min(x,a)=b;Max(c,x)=d;
这个是最大公约数和最小公倍数的基本性质。
通过这两个条件,我们可以算出x的取值范围。因为不同质因数之间是互不影响的,所以就直接乘起来即可。
对于 109 数分解质因数可以先把1到100000之间的质数筛出来,然后枚举1到100000以内的质数,如果这样之后还有剩余的部分那么就是最后那个剩下的质数了。

【代码】

#include <cstdio>

int a0,a1,b0,b1,t;

inline int gcd(int x,int y){
    int i,j;
    if(x==0) return y;
    if(y==0) return x;
    for(i=0;(x&1)==0;i++) x>>=1;
    for(j=0;(y&1)==0;j++) y>>=1;
    if(j<i) i=j;
    while(1) {
        if(x<y) x^=y,y^=x,x^=y;
        if((x-=y)==0) return y<<i;
        while((x&1)==0) x>>=1;
    }
}

bool judge(int x) {
    return !(x%a1)&&1==gcd(x/a1,a0/a1)&&1==gcd(b1/b0,b1/x);
}

int main(){
    scanf("%d",&t);
    while(t--) {
        scanf("%d%d%d%d",&a0,&a1,&b0,&b1);
        int p=a0/a1;
        int ans=0;
        for(int k=1;k*k<=b1;k++) {
            if(!(b1%k)) {
                ans+=judge(k);
                if(k*k!=b1) 
                    ans+=judge(b1/k);
            }
        }
        printf("%d\n",ans);
    }
    return 0;
}

【小Y的智力游戏】(Game.pas/c/cpp Time:1s Memory:256M)

【问题描述】

小Y最近迷上了一款智力游戏。(当然小Y还是很好学的)
这款智力游戏就是让你从1到N这N个数中,选取若干个不相等的正整数,使得它们的乘积为一个完全平方数,同时,这个乘积也将成为你的得分。
他(或她,以后这个括号就省略了)想知道最大得分对1000000007的模值。

【输入】

输入文件名game.in
一行一个正整数N,代表数字的个数。

【输出】

输出文件名game.out
一行一个正整数,代表最大得分对1000000007的模值。

【输入输出样例】

Game.in Game.out
3 1

【数据范围】

对于30%的数据,保证有n≤50。
对于60%的数据,保证有n≤1000。
对于70%的数据,保证有n≤10000。
对于80%的数据,保证有n≤100000。
对于90%的数据,保证有n≤1000000。
对于100%的数据,保证有n≤3000000。
【题解】

将 n! 唯一分解,然后将指数为奇数的质因子的指数减去一,得到的唯一分解式就是答案

【代码】

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

typedef long long LL;
const int mod = 1000000007;
const int size = 3000010;
LL n,ans=1,tmp;
LL prime[size],cl[size],fir[size];
bool no_prime[size];

void fenjie(int x) {
    if(x==1) 
        return ;
    LL ret = fir[x];
    while(x%prime[ret]==0) {
        x/=prime[ret];
        cl[ret]++;
    }
    fenjie(x);
}

LL powermod(LL x,LL y,LL p) {
    if(y==0) 
        return 1;
    if(y==1) 
        return x%p;
    LL ret = powermod(x,y/2,p);
    ret = ret*ret%p;
    if(y&1)
        ret = ret*(x%p)%p;
    return ret;
}

int main() {
    freopen("game.in","r",stdin);
    freopen("game.out","w",stdout);
    scanf("%lld",&n);
    for(LL i=2;i<=n;i++) {
        if(!no_prime[i]) {
            prime[++tmp]=i;
            fir[i]=tmp;
        }
        for(LL j=1;prime[j]*i<=n;j++) {
            fir[prime[j]*i]=j;
            no_prime[prime[j]*i]=true;
            if(i%prime[j]==0)
                break;
        }
    }
    for(LL i=2;i<=n;i++) 
        fenjie(i);
    for(LL i=1;i<=tmp;i++) {
        if(cl[i]&1) 
            ans = ans*powermod(prime[i],cl[i]-1,mod)%mod;
        else 
            ans = ans*powermod(prime[i],cl[i],mod)%mod;
    }
    printf("%lld\n",ans);
    return 0;
}

【小Y的绝对战争】(War.pas/c/cpp Time:1s Memory:256M)

【问题描述】

小Y与大黄爆发了一场绝对要胜利的战争。(原因是大黄生活作风问题)
小Y现在拥有N个城池,每个城池都有一个强大值Wi。现在没有一条通路连接任意两个城池(通路是双向的)。现在小Y想顺次修建若干条通路,使得每修建一条通路都连接了两个原本不连通的城池(联通的定义是两个城池之间存在一条由通路构成的路径)。每修建一条通路IJ,那么安全值就会增加Gcd(Wi,Wj)。为了确保这场战争的胜利,小Y想知道,可能的最大安全值是多少(囧)。

【输入】

输入文件名为war.in。
第一行一个正整数N,代表城池的个数。
接下来N行,每行一个正整数,代表这个城市的强大值。

【输出】

输出文件名为war.out。
一行一个整数,代表最大的安全值。

【输入输出样例】

War.in
4
1
2
3
4

War.out

4

【数据范围】

对于30%的数据,保证有n≤1000。
对于100%的数据,保证有n≤1000000, 任意W小于等于1000000。
【题解】

这是显然是求一颗最大生成树。首先我们可以想到一个Kruskal的解法。也就是N^2LogN的。但是,很明显因为权值在1到1000000所以不同权值也最多只有1000000,也就是说,可以直接从大到小枚举权值,将点合并。对于一个权值I,可以取的所有点就是I的权值的倍数。这样,时间复杂度就降低为 O(NlnN)

考试时我是直接 O(n2) 出解

【代码】

暂无

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值