1 / 37

习题选讲

习题选讲. 赵浩泉 wxyz202@soj.me. 数论. 1500 Prime Gap 1259 Sum of Consecutive Primes 123 1 The Embarrassed Cryptography 1240 Faulty Odometer 1214 信号分析 1203 The Cubic End 1099 Packing Passengers 1014 Specialized Four-Dig 1119 Factstone Benchmark. 1500 Prime Gap. 题目大意:

mili
Download Presentation

习题选讲

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. 习题选讲 赵浩泉 wxyz202@soj.me

  2. 数论 • 1500 Prime Gap • 1259 Sum of Consecutive Primes • 1231 The Embarrassed Cryptography • 1240 Faulty Odometer • 1214 信号分析 • 1203 The Cubic End • 1099 Packing Passengers • 1014 Specialized Four-Dig • 1119 Factstone Benchmark

  3. 1500 Prime Gap • 题目大意: • 给出一个正整数k,计算出两个相邻的素数,使得k在这两个素数之间,求出两个素数之差。如果不存在这两个素数则输出0。

  4. 1500 Prime Gap • 解题思路: • 题目等价于求出小于等于k的最大素数与大于等于k的最小素数,并求出它们的差。 • 从k分别向下和向上枚举每个整数,判断是否为素数,直到找到这两个素数。

  5. 1500 Prime Gap boolisprime(int n) { if (n!=2&&n%2==0) return false; for (inti=3;i*i<=n;i+=2) if (n%i==0) return false; return true; } for (i=k;!isprime(i);i--); for (j=k;!isprime(j);j++);

  6. 1259 Sum of Consecutive Primes • 题目大意: • 给出一个正整数,求出它有多少种方法可以表示成连续的素数的和。 • 例如53 = 5 + 7 + 11 + 13 + 17 = 53,共有两种方法。 • 数据范围为[2, 10000]

  7. 1259 Sum of Consecutive Primes • 解题思路: • 先求出10000以内的所有素数。 • 对每个输入,枚举连续的素数的起点,寻找是否有一段连续的素数与它相等,如果有则累加答案。

  8. 1259 Sum of Consecutive Primes • p[0]=2;np=1; • for (i=3;i<10000;i+=2) { • isprime=true; • for (j=0;j<np;j++) { • if (p[j]>100) break; • if (i%p[j]==0) isprime=false; • } • if (isprime) {p[n]=i;np++;} • }

  9. 1259 Sum of Consecutive Primes • int cal(int n) { • int ans=0; • for (int i=0;i<np;i++) { • int j=i,s=0; • while (s<n&&j<np) {s+=p[j];j++;} • if (s==n) ans++; • } • return ans; • }

  10. 1231 The Embarrassed Cryptography • 题目大意: • 给出两个正整数K和L,问K是否存在小于L的质因数,有的话则找出最小的质因数。 • 4 <= K <= 10100, 2 <= L <= 106

  11. 1231 The Embarrassed Cryptography • 解题思路: • 先预处理不超过106的所有素数。(筛法) • 对每个不超过L的素数,检查是否能整除K。 • 高精度除法。(压缩)

  12. 1231 The Embarrassed Cryptography memset(prime,true,sizeof(prime)); p[0]=2; np=1; //prime number counter for (i=3;i<maxn;i+=2) { if (prime[i]==true) { p[np]=i; np++; for (j=i+i;j<maxn;j+=i) prime[i]=false; } }

  13. 1231 The Embarrassed Cryptography m=strlen(s); if (m%9==0) k=0; else k=9-m%9; for (i=m;i>=0;i--) s[i+k]=s[i]; for (i=0;i<k;i++) s[i]='0'; m=strlen(s)/9; for (i=0;i<m;i++) { x[i]=0; for (j=0;j<9;j++) x[i]=x[i]*10+s[i*9+j]-'0'; }

  14. 1231 The Embarrassed Cryptography ans=-1; for (i=0;i<np&&p[i]<l;i++) { temp=0; for (j=0;j<m;j++) temp=((long long)temp * 1000000000+x[j]) % p[i]; if (temp==0) { ans=p[i]; break; } }

  15. 1240 Faulty Odometer • 题目大意: • 有个损坏的里程表,不能显示数字4,会从数字3直接跳到数字5。 • 给出里程表的读数,求出实际里程。

  16. 1240 Faulty Odometer • 解题思路: • 里程表能显示的数字为”012356789”,总共9个,等价于九进制。以九进制的方式计算实际里程。

  17. 1240 Faulty Odometer • int cal(int n) { • int s=0,k=1,m=n; • while (n>0){ • int x=n%10; • n/=10; • if (x>4) x--; • s+=x*k; • k*=9; • } • return s; • }

  18. 1214 信号分析 • 题目大意: • 数列a1=1, a3=3 • a2n = an • a4n+1 = 2*a2n+1 – an • a4n+3 = 3*a2n+1 - 2*an • 给出L,求1<=i<=L中aL=L的个数

  19. 1214 信号分析 • 解题思路: • 找规律。按二进制找。 • a(1)=1 a(10)=1 a(11)=11 a(100)=1 a(101)=101 a(110)=11 a(111)=1111 • 猜想规律:数列的第n项为n的二进制串的倒置。

  20. 1214 信号分析 • 证明:用数学归纳法证明 • 当n=1和3时,a(1)=1,a(11)=11满足。 • 设n=xyz,则a(xyz0)=a(xyz)=zyx=0zyx,满足; • a(xyz01)=2*a(xyz1)-a(xyz)=1zyx0-zyx =10zyx,满足; • a(xyz11)=3*a(xyz1)-2*a(xyz)=1zyx0+1zyx-zyx0 =11zyx,满足。 • 因此得到证明。

  21. 1214 信号分析 • 问题转换成求1<=i<=L的二进制里有多少个是回文串。 • 枚举构成回文串的其中一半数字,从而构造得到回文串,再与L比较大小。 • L最多为32位,因此枚举的二进制串最多为16位。

  22. 1214 信号分析 • void dfs(unsigned n,unsigned lev) { • if (lev==0) { • cal(n); • return; • } • dfs(n<<1,lev-1); • dfs((n<<1)+1,lev-1); • return; • } • ans=0; • dfs(0,16);

  23. 1214 信号分析 • void cal(unsigned n) { • if (n==0) return; • unsigned temp=n,l=0; • while (temp>0) { • temp>>=1; • l++; • } • temp=(n<<l)|reverse(n); • if (temp<=L) ans++; • temp=(n<<(l-1))|reverse(n>>1); • if (temp<=L) ans++; • return; • }

  24. 1214 信号分析 • unsigned reverse(unsigned n) { • unsigned ret=0; • while (n>0) { • ret=(ret<<1)|(n&1); • n>>=1; • } • return ret; • }

  25. 1203 The Cubic End • 题目大意: • 如果一个数字串,以1,3,7,9结尾,则会有一个数,它的三次方以这个数字串结尾,且长度不会超过这个数字串。现在给出这个数字串,求出这个数。

  26. 1203 The Cubic End • 解题思路: • 从低位向高位枚举,尝试用每个数字填入这个位置,检查所得到的尾数是否相符,相符则下一个位,直至枚举完所有位置。 • 检查尾数用三重循环(三次方),保存进位。

  27. 1203 The Cubic End scanf("%s",s); k=strlen(s); for (i=0;i<k;i++) n[i]=s[k-i-1]-48; z=0; for (i=0;i<k;i++){ for (m[i]=0;m[i]<=9;m[i]++){ temp=z; for (a=0;a<=i;a++) for (b=0;a+b<=i;b++){ c=i-a-b; temp=temp+m[a]*m[b]*m[c]; } if (temp%10==n[i]) break; } z=temp/10; } for (i=k-1;i>=0;i--) if (m[i]!=0) break; for (;i>=0;i--) printf("%d",m[i]);

  28. 1099 Packing Passengers • 题目大意: • 有两种飞机A和B,花费分别为costA和costB,容量分别为passengersA和passengersB。现在要N个乘客,每个飞机都要完全装满乘客才能起飞,问最小费用。

  29. 1099 Packing Passengers • 解题思路: • 当A,B其中一个容量为0时特判。 • 求出两种飞机的性价比,使得性价比低的飞机尽量少。 • 从多到少枚举性价比高的飞机的数量,如果剩余的乘客都能被另一种飞机装满,则存在解。

  30. 1099 Packing Passengers • bool sol(long longai,long long bi,long long &a,long long &b,long long n) { • a=n/ai; • while ((n-a*ai)%bi!=0) { • if (a>0) a--; • else return false; • } • b=(n-a*ai)/bi; • return true; • } • if ((double)ax/ai<=(double)bx/bi) • c=sol(ai,bi,a,b,n); • else • c=sol(bi,ai,b,a,n);

  31. 1014 Specialized Four-Dig • 题目大意: • 求出所有在十进制,十二进制,十六进制下各位数字之和相等的四位十进制数。

  32. 1014 Specialized Four-Dig • 解题思路: • 枚举所有四位数,求出十进制,十二进制,十六进制下各位数字之和,再判断是否相等。

  33. 1014 Specialized Four-Dig • int sum(int i,int base) { • int s=0; • while (i>0) { • s+=i%base; • i/=base; • } • return s; • } • bool check(int i) { • return sum(i,10)==sum(i,12)&&sum(i,10)==sum(i,16); • }

  34. 1119 Factstone Benchmark • 题目大意: • 1960年发行了4位计算机,从此以后每过10年,计算机的位数变成两倍。输入某一个年份,求出在这个年份的最大的整数n使得n!能被该年份计算机的一个字表示。

  35. 1119 Factstone Benchmark • 解题思路: • 先求出年份对应的字长。例如1981年16位。 • 用科学记数法表示阶乘,以2为底,从指数可以得到位数,与字长比较即可。

  36. 1119 Factstone Benchmark x=k=1; m=(1<<(n/10-194)); for (i=1;k<=m;i++){ x*=i; while (x>=2){ x/=2; k++; } if (k<=m) ans=i; }

  37. 谢谢!

More Related