习题选讲_数论

Download Report

Transcript 习题选讲_数论

习题选讲
赵浩泉
[email protected]
数论









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
2
2011-11-23
1500 Prime Gap
题目大意:
 给出一个正整数k,计算出两个相邻的素
数,使得k在这两个素数之间,求出两个素
数之差。如果不存在这两个素数则输出0。

3
2011-11-23
1500 Prime Gap
解题思路:
 题目等价于求出小于等于k的最大素数与大
于等于k的最小素数,并求出它们的差。
 从k分别向下和向上枚举每个整数,判断是
否为素数,直到找到这两个素数。

4
2011-11-23
1500 Prime Gap
bool isprime(int n) {
if (n!=2&&n%2==0)
return false;
for (int i=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++);
5
2011-11-23
1259 Sum of Consecutive Primes
题目大意:
 给出一个正整数,求出它有多少种方法可
以表示成连续的素数的和。
 例如53 = 5 + 7 + 11 + 13 + 17 = 53,共有
两种方法。
 数据范围为[2, 10000]

6
2011-11-23
1259 Sum of Consecutive Primes
解题思路:
 先求出10000以内的所有素数。
 对每个输入,枚举连续的素数的起点,寻
找是否有一段连续的素数与它相等,如果
有则累加答案。

7
2011-11-23
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++;}
}
8
2011-11-23
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;
}
9
2011-11-23
1231 The Embarrassed Cryptography
题目大意:
 给出两个正整数K和L,问K是否存在小于L
的质因数,有的话则找出最小的质因数。


4 <= K <= 10100 , 2 <= L <= 106
10
2011-11-23
1231 The Embarrassed Cryptography
解题思路:
 先预处理不超过106 的所有素数。(筛法)
 对每个不超过L的素数,检查是否能整除
K。
 高精度除法。(压缩)

11
2011-11-23
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;
}
}
12
2011-11-23
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';
}
13
2011-11-23
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;
}
}
14
2011-11-23
1240 Faulty Odometer
题目大意:
 有个损坏的里程表,不能显示数字4,会从
数字3直接跳到数字5。
 给出里程表的读数,求出实际里程。

15
2011-11-23
1240 Faulty Odometer
解题思路:
 里程表能显示的数字为”012356789”,总
共9个,等价于九进制。以九进制的方式计
算实际里程。

16
2011-11-23
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;
}
17
2011-11-23
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的个数

18
2011-11-23
1214 信号分析
解题思路:
 找规律。按二进制找。
 a(1)=1 a(10)=1 a(11)=11 a(100)=1
a(101)=101 a(110)=11
a(111)=1111
 猜想规律:数列的第n项为n的二进制串的
倒置。

19
2011-11-23
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,满足。
因此得到证明。
20
2011-11-23
1214 信号分析
问题转换成求1<=i<=L的二进制里有多少个
是回文串。
 枚举构成回文串的其中一半数字,从而构
造得到回文串,再与L比较大小。
 L最多为32位,因此枚举的二进制串最多为
16位。

21
2011-11-23
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);
22
2011-11-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;
}
23
2011-11-23
1214 信号分析








unsigned reverse(unsigned n) {
unsigned ret=0;
while (n>0) {
ret=(ret<<1)|(n&1);
n>>=1;
}
return ret;
}
24
2011-11-23
1203 The Cubic End
题目大意:
 如果一个数字串,以1,3,7,9结尾,则
会有一个数,它的三次方以这个数字串结
尾,且长度不会超过这个数字串。现在给
出这个数字串,求出这个数。

25
2011-11-23
1203 The Cubic End
解题思路:
 从低位向高位枚举,尝试用每个数字填入
这个位置,检查所得到的尾数是否相符,
相符则下一个位,直至枚举完所有位置。
 检查尾数用三重循环(三次方),保存进
位。

26
2011-11-23
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]);
27
2011-11-23
1099 Packing Passengers
题目大意:
 有两种飞机A和B,花费分别为costA和
costB,容量分别为passengersA和
passengersB。现在要N个乘客,每个飞
机都要完全装满乘客才能起飞,问最小费
用。

28
2011-11-23
1099 Packing Passengers
解题思路:
 当A,B其中一个容量为0时特判。
 求出两种飞机的性价比,使得性价比低的
飞机尽量少。
 从多到少枚举性价比高的飞机的数量,如
果剩余的乘客都能被另一种飞机装满,则
存在解。

29
2011-11-23
1099 Packing Passengers













bool sol(long long ai,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);
30
2011-11-23
1014 Specialized Four-Dig
题目大意:
 求出所有在十进制,十二进制,十六进制
下各位数字之和相等的四位十进制数。

31
2011-11-23
1014 Specialized Four-Dig
解题思路:
 枚举所有四位数,求出十进制,十二进
制,十六进制下各位数字之和,再判断是
否相等。

32
2011-11-23
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);
}
33
2011-11-23
1119 Factstone Benchmark
题目大意:
 1960年发行了4位计算机,从此以后每过10
年,计算机的位数变成两倍。输入某一个
年份,求出在这个年份的最大的整数n使得
n!能被该年份计算机的一个字表示。

34
2011-11-23
1119 Factstone Benchmark
解题思路:
 先求出年份对应的字长。例如1981年16
位。
 用科学记数法表示阶乘,以2为底,从指数
可以得到位数,与字长比较即可。

35
2011-11-23
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;
}
36
2011-11-23
谢谢!
37
2011-11-23