sduacm16级寒假训练 素筛 快速幂 GCD
2017-02-03 15:20
141 查看
https://vjudge.net/contest/149323
Password:acmlab2016
A - A
【题意】
给你一个数,将它拆分成若干个连续素数的和,问有多少种方案
【思路】
给的数在2~10000,那么可以先处理出该范围的所有素数,去枚举连续素数的和,与给的数做判断.
【Code】
B - B
【题意】
给你[L,U]的区间,1<=L< U<=2,147,483,647,U-L<=1000000;
求出该区间内相邻最近和最远的两个素数,如果不存在两个素数,输出”There are no adjacent primes.”;
【思路】
数据范围那么大,枚举肯定不行的.
但是sqrt(2,147,483,647)≈46341,我们可以处理出[1,50000]范围内的素数,用这些素数去筛选区间内的数,
最后就是需要注意L=1的情况以及U=2,147,483,647的情况.
1是肯定不会被筛的,区间就换成[2,U].
U=2,147,483,647时,i++会爆掉..
【Code】
C - C
【题意】
求(A1^B1+A2^B2+ … +AH^BH)mod M的值.
【思路】
快速幂.
【Code】
D - D
【题意】
p是素数,
那么p一定不是base-a pseudoprime;
p不是素数,
判断是否a^p与a关于模p同余,即判断a^p %p==a是否成立.
成立则p为base-a pseudoprime.
【思路】
注意p%i==0和!p%i,一开始因为这个纠结半天.
【Code】
E - E
【题意】
一条首尾相接的数轴,两只青蛙,初始位置x、y,每次分别跳m、n求两只青蛙跳了多少次能相遇。
【思路】
构造方程 (x + m * s) - (y + n * s) = k * l(k = 0, 1, 2,…)
变形为 (n-m) * s + k * l = x - y。即转化为模板题,a * x + b * y = n,是否存在整数解。
然后用拓展欧几里得求出一组最小的可行解即可。
【Code】
Password:acmlab2016
A - A
【题意】
给你一个数,将它拆分成若干个连续素数的和,问有多少种方案
【思路】
给的数在2~10000,那么可以先处理出该范围的所有素数,去枚举连续素数的和,与给的数做判断.
【Code】
#include<cstdio> const int Mx=10000; int p[Mx+10]; bool f[Mx+10]; int main() { int n,ans,tot=0,sum; for (int i=2;i<=Mx;i++) if (!f[i]) { tot++; p[tot]=i; int j=i*2; while (j<=Mx) { f[j]=true; j+=i; } } while(scanf("%d",&n)&&n) { ans=0; for (int i=1;i<=tot&&p[i]<=n;i++) { sum=0; for (int j=i;j<=tot&&p[j]<=n;j++) { sum+=p[j]; if (sum==n) { ans++; break; } if (sum>n) break; } } printf("%d\n",ans); } }
B - B
【题意】
给你[L,U]的区间,1<=L< U<=2,147,483,647,U-L<=1000000;
求出该区间内相邻最近和最远的两个素数,如果不存在两个素数,输出”There are no adjacent primes.”;
【思路】
数据范围那么大,枚举肯定不行的.
但是sqrt(2,147,483,647)≈46341,我们可以处理出[1,50000]范围内的素数,用这些素数去筛选区间内的数,
最后就是需要注意L=1的情况以及U=2,147,483,647的情况.
1是肯定不会被筛的,区间就换成[2,U].
U=2,147,483,647时,i++会爆掉..
【Code】
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int Mx=50000; bool f[1000010]; int p[Mx+10]; int main() { int n,m,tot=0,x1,x2,y1,y2; for (int i=2;i<=Mx;i++) if (!f[i]) { tot++; p[tot]=i; int j=i*2; while (j<=Mx) { f[j]=true; j+=i; } } while (scanf("%d%d",&n,&m)!=EOF) { int nc=0,mx=0,mi=100000000,k; memset(f,0,sizeof(f)); for (int i=1;i<=tot&&p[i]<=m;i++) { k=n/p[i]; if (n%p[i]!=0) k++; if (k==1) k++; k=k*p[i]; while (k>=n&&k<=m) { f[k-n]=true; k+=p[i]; } } for (int i=max(n,2);i<=m&&i-n<=m-n;i++) if (!f[i-n]) { if (!nc){ nc=i; continue; } if (i-nc>mx) { mx=i-nc; x1=nc; x2=i; } if (i-nc<mi) { mi=i-nc; y1=nc; y2=i; } nc=i; } if (mi!=100000000) printf("%d,%d are closest, %d,%d are most distant.\n",y1,y2,x1,x2); else printf("There are no adjacent primes.\n"); } return 0; }
C - C
【题意】
求(A1^B1+A2^B2+ … +AH^BH)mod M的值.
【思路】
快速幂.
【Code】
#include<cstdio> int qpow(int a,int b,int c) { int tot=1; while (b) { if (b&1) tot=((long long)tot*a)%c; a=((long long)a*a)%c; b=b>>1; } return tot; } int main() { int n,m,T,ans,a,b; scanf("%d",&T); while (T--) { scanf("%d",&m); scanf("%d",&n); ans=0; for (int i=1;i<=n;i++) { scanf("%d %d",&a,&b); ans=(ans+qpow(a,b,m))%m; } printf("%d\n",ans); } }
D - D
【题意】
p是素数,
那么p一定不是base-a pseudoprime;
p不是素数,
判断是否a^p与a关于模p同余,即判断a^p %p==a是否成立.
成立则p为base-a pseudoprime.
【思路】
注意p%i==0和!p%i,一开始因为这个纠结半天.
【Code】
#include<cstdio> int quickpow(int a,int b,int c) { int tot=1; while(b) { if (b&1) tot=((long long)tot*a)%c; a=((long long)a*a)%c; b=b>>1; } return tot; } int main() { int a,p; while (scanf("%d%d",&p,&a)&&a) { int s=1; for (int i=2;i*i<=p;i++) if (p%i==0){ s=0; break; } if (s) printf("no\n"); else{ s=quickpow(a,p,p); if (s==a) printf("yes\n"); else printf("no\n"); } } }
E - E
【题意】
一条首尾相接的数轴,两只青蛙,初始位置x、y,每次分别跳m、n求两只青蛙跳了多少次能相遇。
【思路】
构造方程 (x + m * s) - (y + n * s) = k * l(k = 0, 1, 2,…)
变形为 (n-m) * s + k * l = x - y。即转化为模板题,a * x + b * y = n,是否存在整数解。
然后用拓展欧几里得求出一组最小的可行解即可。
【Code】
#include<cstdio> long long gcd(long long x,long long y) { if(y==0) return x; return gcd(y,x%y); } void exgcd(long long a,long long b,long long &x,long long &y) { if(b==0) { x=1; y=0; return; } exgcd(b,a%b,x,y); long long t= x; x=y; y=t-a/b*y; return; } int main() { long long x,y,m,n,l; while(~scanf("%lld %lld %lld %lld %lld",&x,&y,&m,&n,&l)) { long long a=n-m,b=l,c=x-y,p,q; long long d=gcd(a,b); if(c%d) { puts("Impossible"); continue; } a/=d,b/=d,c/=d; exgcd(a,b,p,q); p*=c; long long t=p%b; while(t<0) t+=b; printf("%lld\n",t); } }