【数学】test20170304
【小 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。
【Analysis】
将1~n逐个分解质因数(等效于分解n!),若质因子指数为偶,直接乘,否则指数-1再乘,求n!中质数k的次数s(k)=n/k+n/(k^2)+n/(k^3)+......
【code】
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 6 const int A = 3e6+10, mod = 1e9+7; 7 8 int n,s; 9 int p[A],ex[A],sum[A]; 10 unsigned long long ans=1,x,k,y; 11 12 int power(int a,int b) 13 { 14 x=a;k=1; 15 while(b) 16 { 17 if(b&1)k=(k*x)%mod; 18 x=(x*x)%mod; 19 b>>=1; 20 } 21 return k; 22 } 23 24 void prime() 25 { 26 for(int i=2;i<=n;++i) 27 { 28 if(!ex[i])p[++s]=i; 29 for(int j=1;j<=s&&p[j]*i<=n;++j) 30 { 31 ex[p[j]*i]=1; 32 if(i%p[j]==0)break; 33 } 34 } 35 } 36 37 void calc(int n,int p,int &s) 38 { 39 y=p; 40 while(y<=n)s+=(n/y),y*=p; 41 } 42 43 int main() 44 { 45 freopen("game.in","r",stdin); 46 freopen("game.out","w",stdout); 47 scanf("%d",&n); 48 prime(); 49 for(int i=1;i<=s;++i)calc(n,p[i],sum[i]); 50 for(int j=1;j<=s;++j) 51 if(sum[j]) 52 { 53 if(sum[j]%2==1)--sum[j]; 54 if(sum[j])ans=(ans*power(p[j],sum[j]))%mod; 55 } 56 printf("%llu\n",ans); 57 return 0; 58 }
【小 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。
【Analysis】
对于任意质数,设起在A中次数为a,在A1中次数为a1,在B中次数为b,在B1中次数为b1,在X中次数为x,则min(a,a1)=x,max(b,b1)=x;据此求x的取值范围
【code】
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 6 const int A = 1e6; 7 8 int n,maxn,pre,k,x,y,q,s,z; 9 int w[A+10],vis[A+10][2],f[A+10]; 10 long long ans; 11 12 int find(int x) 13 { 14 if(x!=f[x])f[x]=find(f[x]); 15 return f[x]; 16 } 17 18 int main() 19 { 20 freopen("war.in","r",stdin); 21 freopen("war.out","w",stdout); 22 scanf("%d",&n); 23 for(int i=1;i<=n;++i)f[i]=i; 24 for(int i=1;i<=n;++i) 25 { 26 scanf("%d",&w[i]); 27 if(w[i]>maxn)maxn=w[i]; 28 if(!vis[w[i]][0]){vis[w[i]][0]=1;vis[w[i]][1]=i;} 29 else {ans+=w[i];f[vis[w[i]][1]]=i;++s;}// 30 } 31 32 for(int i=maxn;i>=1;--i)// 33 { 34 pre=0; 35 for(int j=1;i*j<=maxn;++j) 36 { 37 k=i*j; 38 if(vis[k][0]) 39 { 40 if(!pre)pre=vis[k][1],q=k; 41 else 42 { 43 x=find(pre);y=find(vis[k][1]); 44 if(x!=y) 45 { 46 ans+=i;f[x]=y;++s; 47 } 48 } 49 } 50 } 51 if(s==n-1)break; 52 } 53 printf("%lld\n",ans); 54 return 0; 55 }
【小 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。
【Analysis】
从大到小枚举边权,vis[i][0]记存在权值为i的点,vis[i][1]记初始父亲,要处理点权相同的情况
【code】
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 6 const int size = 45000; 7 8 int A,A1,B,B1,a,a1,b,b1,x,s,sum,l,r,T,bo,bb; 9 int p[size+10],ex[size+10]; 10 long long ans=1; 11 12 void prime() 13 { 14 for(int i=2;i<=size;++i) 15 { 16 if(!ex[i])p[++s]=i; 17 for(int j=1;j<=s&&p[j]*i<=size;++j) 18 { 19 ex[p[j]*i]=1; 20 if(i%p[j]==0)break; 21 } 22 } 23 } 24 25 int solve(int &a,int b) 26 { 27 sum=0; 28 while(a%b==0)++sum,a/=b; 29 return sum; 30 } 31 32 int main() 33 { 34 freopen("homework.in","r",stdin); 35 freopen("homework.out","w",stdout); 36 prime(); 37 scanf("%d",&T); 38 while(T--) 39 { 40 ans=1;bo=0; 41 scanf("%d%d%d%d",&A,&A1,&B,&B1); 42 if(B1%A1){printf("0\n");continue;} 43 bb=B1; 44 for(int i=1;i<=s;++i) 45 { 46 if(p[i]>bb) break; 47 x=-1;l=-1;r=-1;// 48 a=solve(A,p[i]); 49 a1=solve(A1,p[i]); 50 b=solve(B,p[i]); 51 b1=solve(B1,p[i]); 52 if(a==a1)l=a; 53 else x=a1; 54 if(b==b1)r=b; 55 else 56 { 57 if(x>=0&&b1!=x){bo=1;break;} 58 x=b1; 59 } 60 if(l>r&&l>=0&&r>=0){bo=1;break;} 61 if(x<0)ans*=(r-l+1); 62 } 63 if(A>1&&A1>1)ans*=2; 64 if(B>1&&B1>1)ans*=2; 65 if(bo)printf("0\n"); 66 else printf("%lld\n",ans); 67 } 68 return 0; 69 }