周期串java_算法竞赛入门经典 第五章 基础题目选讲

5.1.1 WERTYU

7bc351454309c1a6366583a54fa6b93e.png

bd29405b8ec00598d17bb407a70de102.png

虽然可以用if else或者switch进行这种变换,但是这样是非常麻烦的,会存在很多的分支,显得程序很臃肿。

一个优雅的解决方法是采用常量数组的方式。

#include

char *s = "`1234567890-=qwertyuiop[]asdfghjkl;'\zxcvbnm,./"; // 常量数组能够很好解决按键位移问题

int main(){

int i,c;

while((c=getchar())!=EOF){

for(i=1; s[i] && c!=s[i]; i++);

if(s[i]) putchar(s[i-1]); // 如果是以上s字符串里面的字符,可以变成它的前一个

else putchar(c); // 否则,空格等别的占位符,保持不变

}

return 0;

}

5.1.3 周期串问题

6c75b9d63617250a9fe6ede9ac3d3190.png

#include

#include

int main(){

char word[100];

scanf("%s",word); // %s要求的是一个地址,字符串的名字就是第一个字符的地址

int len = strlen(word);

for(int i=1; i

if(len%i==0){

int ok=1;

for(int j=i; j

if(word[j]!=word[j%i]){ ok=0; break; }

}

// i是从小开始的递增的,因此只要找到第一个ok的周期就可以收工break了

if(ok){ printf("%s",word); break; }

}

}

5.2.1 小学生算术

a7589a7deedba8bd71e40efd64ddd5b8.png

#include

int main(void) {

int a, b;

scanf("%d%d",&a,&b);

if(!a && !b) return ;

int c=0, ans=0;

for(int i=9; i>=0; i--){ // 最高为九位,因此需要进行9次(除以10的)循环

c=(a%10 + b%10 + c) > 9 ? 1 : 0; // c负责保存进位

// 注意,当前位数a、b两者相加时还要考虑小一倍数的进位

ans +=c; // 每次有进位就记入ans

a/=10;

b/=10;

printf("%d",c);

}

printf("%d",ans);

}

5.2.2 阶乘的精确值

9f5d2a578191e609b1a95afedcac4601.png

dbeb3e0b58488eec34a2a1a563830dce.png

#include

#include

const int maxn = 3000;

int main(void) {

int f[maxn]; // 定义数组,由于1000!约等于4*10^2567,因此数组可以取3000位

int n, j, i;

scanf("%d",&n);

memset(f,0,sizeof(f)); // 将f从f[0]到f[2999]全部置零

f[0]=1; // 对于n<2的那两个阶乘,结果均为1,这也是为什么i要从2开始

for(i=2; i<=n; i++){

int c=0;

for(j=0; j

int s=f[j]*i+c; // 乘完得出来的数为s

f[j] = s%10; // 取s的个位当作当前第j位的数字

c = s/10; // s的十位作为大一位数的进位

}

}

for(j=maxn-1; j>=0; j--) if(f[j]) break; // 从后往前数,直到第一个非零数字出现,也是乘积的最大位数

for(i=j; i>=0; i--){ // 逆序表示,个位是f[0]、十位是f[1]……,方便进位,但是输出时要从后往前输出

printf("%d",f[i]);

}

printf("\n");

}

然后以下就是根据上面阶乘的原理用java做出来的大数乘法器:

import java.util.Scanner;

public class Main {

// inspired by ‘5.2.2阶乘的精确值’ 的 乘法器

public static void main(String[] args) {

final int maxn=3000;

int[] f = new int[maxn];

int i, j, carry;

Scanner s = new Scanner(System.in);

String a = s.next();

String b = s.next();

// System.out.print("a="+a+", b="+b+"\n");

int len_a = a.length();

int len_b = b.length();

// System.out.print("a.len="+len_a+", b.len="+len_b+"\n");

// f全部置零

for(int k=len_a-1; k>=0; k--){

f[k] = 0;

}

//倒序,从低位(个位)开始计算,为了方便计算进位,将数组f的下标低位设置为结果的低位

for(i=len_a-1; i>=0; i--){

for(j=len_b-1; j>=0; j--){

// 个位是0,十位是1...这样第i+j位就是两个当前被乘数的和所在的位置(乘法笔算)

f[(len_a-i-1)+(len_b-j-1)]+=(a.charAt(i)-'0')*(b.charAt(j)-'0');

}

}

// 把数组f中原先保留的数现在变成个位数,通过进位

for(i=0; i

carry = f[i]/10;

f[i] = f[i]%10;

f[i+1] += carry;

}

j=maxn-1;

// for循环的作用仅仅是让j从后向前移动,消除首位零,直到第一个非零项

for(; j>=0; j--) {

if(f[j]!=0) {

break;

}

}

for(i=j; i>=0; i--){

System.out.print(f[i]);

}

}

}

这个大数乘法器能够实现超过2^31(Integer的尺寸)的数字的乘法

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值