数学考试 1

来源:互联网 发布:gta5没有网络能玩吗 编辑:程序博客网 时间:2024/05/01 01:07

NOIP2015模拟


这里写图片描述


一、小Y的绝对战争


【问题描述】

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


【输入】

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


【输出】

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


【输入样例】

4
1
2
3
4


【输出样例】

4

【数据范围】

对于 30% 的数据,保证有 n1000
对于 100% 的数据,保证有 n1000000 , 任意 W 小于等于 1000000


Solution

很恶心的题目,连Kruskal都打错了的我果断零分。
因为权值在 11000000 所以不同权值也最多只有 1000000,也就是说,可以直接从大到小枚举权值,将点合并。
对于一个权值 I,可以取的所有点就是 I 的权值的倍数。
这样,时间复杂度就降低为 O(NlnN)
这个,时间复杂度为 O(NlnN) 请自行证明。


Code

#include <iostream>#include <cstdio>#include <algorithm>#define Max(x,y) ((x)>(y)?(x):(y))#define LL long longusing namespace std;LL n,maxn,cnt,ans;LL fa[1000010];LL find(LL x){    LL tmp=x,pre;    while(tmp!=fa[tmp])tmp=fa[tmp];    while(x!=tmp){        pre=fa[x];        fa[x]=tmp;        x=pre;    }    return tmp;}int main(){    freopen("war.in","r",stdin);    freopen("war.out","w",stdout);    scanf("%lld",&n);    for(LL i=1;i<=n;i++){        LL x;        scanf("%lld",&x);        if(fa[x]==x)ans+=x;        fa[x]=x;        maxn=Max(x,maxn);    }    for(LL i=maxn;i>=1&&cnt<n-1;i--){        LL big=maxn/i,tmp,ft;        bool first=true;        for(LL j=1;j<=big;j++)if(fa[i*j]){            if(first)tmp=i*j,ft=find(tmp),first=false;            else{                LL ff=find(i*j);                if(ff==ft)continue;                fa[ff]=ft;ans+=i;cnt++;            }        }    }    printf("%lld\n",ans);    return 0;}

二、小Y的数学作业


【问题描述】

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


【输入】

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


【输出】

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


【输入样例】

2
41 1 96 288
95 1 37 1776


【输出样例】

6
2


【数据范围】

对于 50% 的数据,保证有 1AA1BB110000n100
对于 100% 的数据,保证有 1AA1BB12,000,000,000n2000


Solution

 Gcd(x,A)=A1,Lcm(x,B)=B1Gcd(xA1,AA1)=1,Gcd(B1x,B1B)=1

所以分解质因数:
对于 AA1 里有的质因子,x 的指数必须和 A1 的指数相等;
对于 BB1 里有的质因子,x 的指数必须和 B1 的指数相等。
x 的所有质因子的指数必须大于等于 A1 的指数,小于等于 B1 的指数。
对于一个质因子,若 x 的指数的上界为 a,下界为 b,若 a<b 则无解,否则有 ba+1 种选法。
x 的指数需等于 a,且需等于 b,而 ab,那么小Y就算错了。


Code

#include <iostream>#include <cstdio>#include <cstring>#include <cmath>#define LL long long#define INF 0x3f3f3f3fusing namespace std;LL n,a,a1,b,b1;LL prima[100],primb1[100];LL ca1[100],prima1[100],ca[100],cb1[100],pca[100],pcb1[100],pca1[100];LL need_b[100],need_a[100];LL prime[1000010];bool no_prime[1000010];bool flagb[100],flaga[100];inline LL in(){    char x=getchar();    LL ans=0;    while(x<'0'||x>'9')x=getchar();    while(x>='0'&&x<='9'){ans=ans*10+x-'0';x=getchar();}    return ans;}void start(){    for(LL i=2;i<=1000000;i++){        if(!no_prime[i])prime[++prime[0]]=i;        for(LL j=1;prime[j]*i<=1000000;j++){            no_prime[prime[j]*i]=true;            if(i%prime[j]==0)break;        }    }}int main(){    freopen("homework.in","r",stdin);    freopen("homework.out","w",stdout);    start();    n=in();    while(n--){        memset(flaga,0,sizeof flaga);memset(flagb,0,sizeof flagb);        memset(need_b,0,sizeof need_b);memset(need_a,0,sizeof need_a);        ca1[0]=prima1[0]=ca[0]=pca1[0]=cb1[0]=pca[0]=pcb1[0]=prima[0]=primb1[0]=0;        LL ans=1;        a=in();a1=in();b=in();b1=in();        LL sqra=sqrt(a),sqra1=sqrt(a1),sqrb=sqrt(b),sqrb1=sqrt(b1);        LL tma=a,tma1=a1,tmb=b,tmb1=b1;        for(LL i=1;prime[i]<=sqra;i++){            if(tma%prime[i]==0){                prima[++prima[0]]=prime[i],ca[++ca[0]]=0,pca[++pca[0]]=1;                while(tma%prime[i]==0){                    ca[ca[0]]++;                    tma/=prime[i];                    pca[pca[0]]*=prime[i];                }            }        }        if(tma!=1){prima[++prima[0]]=pca[++pca[0]]=tma;ca[++ca[0]]=1;}        for(LL i=1;prime[i]<=sqra1;i++){            if(tma1%prime[i]==0)prima1[++prima1[0]]=prime[i],ca1[++ca1[0]]=0,pca1[++pca1[0]]=1;            while(tma1%prime[i]==0){                ca1[ca1[0]]++;                tma1/=prime[i];                pca1[pca1[0]]*=prime[i];            }        }        if(tma1!=1){prima1[++prima1[0]]=pca1[++pca1[0]]=tma1;ca1[++ca1[0]]=1;}        for(LL i=1;prime[i]<=sqrb1;i++){            if(tmb1%prime[i]==0)primb1[++primb1[0]]=prime[i],cb1[++cb1[0]]=0,pcb1[++pcb1[0]]=1;            while(tmb1%prime[i]==0){                cb1[cb1[0]]++;                tmb1/=prime[i];                pcb1[pcb1[0]]*=prime[i];            }        }        if(tmb1!=1){primb1[++primb1[0]]=pcb1[++pcb1[0]]=tmb1;cb1[++cb1[0]]=1;}        for(LL i=1;i<=primb1[0];i++){            if(b%primb1[i]!=0)need_b[i]=cb1[i];            else if(b%pcb1[i]==0)need_b[i]=-1;            else need_b[i]=cb1[i];        }        for(LL i=1;i<=prima[0];i++){            if(a1%prima[i]!=0){need_a[i]=0;}            else if(a1%pca[i]==0)need_a[i]=-1;            else{                for(LL j=1;j<=prima1[0];j++)                    if(prima1[j]==prima[i])need_a[i]=ca1[j];            }        }        for(LL i=1;i<=primb1[0];i++){            flagb[i]=false;            for(LL j=1;j<=prima[0];j++){                if(primb1[i]==prima[j]){                    flagb[i]=flaga[j]=true;                    if(need_b[i]==-1&&need_a[j]==-1){                        LL tttt;                        for(LL k=1;k<=prima1[0];k++)if(prima1[k]==prima[j])tttt=ca1[k];                        if(cb1[i]<tttt){ans=0;goto nxt;}                        else ans=ans*(cb1[i]-tttt+1);                    }                    else if(need_b[i]==-1&&need_a[j]!=-1){                        if(need_a[j]>cb1[i]){ans=0;goto nxt;}                    }                    else if(need_a[j]==-1&&need_b[i]!=-1){                        LL tttt;                        for(LL k=1;k<=prima1[0];k++)if(prima1[k]==prima[j])tttt=ca1[k];                        if(need_b[i]<tttt){ans=0;goto nxt;}                    }                    else if(need_a[j]!=-1&&need_b[i]!=-1&&need_a[j]!=need_b[i]){ans=0;goto nxt;}                    break;                }            }            if(!flagb[i]){                if(need_b[i]==-1)ans=ans*(cb1[i]+1);            }        }        for(LL i=1;i<=prima[0];i++)            if(!flaga[i]&&need_a[i]==-1){                ans=INF;                break;            }        nxt:        printf("%lld\n",ans);    }}

三、小Y的智力游戏


【问题描述】

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


【输入】

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


【输出】

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


【输入样例】

3


【输出样例】

1


【数据范围】

对于 30% 的数据,保证有 n50
对于 60% 的数据,保证有 n1000
对于 70% 的数据,保证有 n10000
对于 80% 的数据,保证有 n100000
对于 90% 的数据,保证有 n1000000
对于 100% 的数据,保证有 n3000000


Solution

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


Code

#include <iostream>#include <cstdio>#include <cmath>#define Max(x,y) ((x)>(y)?(x):(y))#define MOD 1000000007#define LL long longusing namespace std;LL n,ans=1;LL prime[3000010];bool no_prime[3000010];LL ci[3000010];LL first[3000010];void work(int x){    if(x==1)return;    LL tmp=first[x];    while(x%prime[tmp]==0){        x/=prime[tmp];        ci[tmp]++;    }    work(x);}LL power(LL x,LL y,LL p){    if(y==0)return 1;    if(y==1)return x%p;    LL tmp=power(x,y/2,p);    tmp=tmp*tmp%p;    if(y&1)tmp=tmp*(x%p)%p;    return tmp;}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[++prime[0]]=i;first[i]=prime[0];}        for(LL j=1;prime[j]*i<=n;j++){            first[prime[j]*i]=j;            no_prime[prime[j]*i]=true;            if(i%prime[j]==0)break;        }    }    for(LL i=2;i<=n;i++)work(i);    for(LL i=1;i<=prime[0];i++){        if(ci[i]&1)ans=ans*power(prime[i],ci[i]-1,MOD)%MOD;        else ans=ans*power(prime[i],ci[i],MOD)%MOD;    }    printf("%lld\n",ans);    return 0;}
1 0
原创粉丝点击