机试指南 cha4 数学问题

机试指南 cha4 数学问题

%
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>

using namespace std;
// 还是A+B : 注意是末尾K位而不是第K位
/*
pow()的返回值为double类型,有时会出现返回误差
解决方法:
double x  = pow(10,k);
int t  = (int)x;// 先(int)(double(pow()))
*/
int main()
{
    int a,b,k;
    while(scanf("%d%d%d",&a,&b,&k)!=EOF)
    {
        if (a == 0 && b == 0)
            break;
        double t = pow(10,k);
        int x = (int)t;
        if ((a-b)%x == 0 )
            cout << -1 << endl;
        else
            cout << a+b <<endl;
    }

    return 0;
}

守形数
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>

using namespace std;
// 守形数
/*
注意N的取值范围为2-100,故只能为低1位或者低2位
*/
int main()
{
    int n ;
    while (cin >> n)
    {
        int i;
        if (n>=2 && n< 10)
            i = 10;
        else
            i = 100;
        int m = n*n; //尽量不用pow()

        if ((m-n)%i == 0)
            cout << "Yes!"<<endl;
        else
            cout << "No!" << endl;
    }

    return 0;
}

数位拆解
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>

using namespace std;
/*
*/
int main()
{
    long x1,x2; // 两个小于10^9的整数,保险起见用long
    int a[15],b[15];//存放两个数的每一位数字
    int sum;
    int i,j;
    while (cin >> x1 >>x2)
    {
        sum = 0;
        i = 0; j = 0 ;
        while (x1 > 0)
        {
            a[i++] = x1%10;
            x1/= 10;
        }
        while (x2 > 0)
        {
            b[j++] = x2%10;
            x2/= 10;
        }
        for (int i1=0;i1<i;i1++)
            for (int j1 = 0;j1<j;j1++)
            sum+= a[i1]*b[j1];
        cout <<sum << endl;
    }

    return 0;
}

进制转换
又一版A+B
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>

using namespace std;
/*
*/
int main()
{
   int m,a,b;
   while (cin>>m>>a>>b)
   {
       if (m == 0)
        break;
       int c = a+b;
       int size = 0;int d[10];
       while (c>0)
       {
           d[size++] =  c%m;
           c = c/m;
       }
       for (int i = size-1;i>=0;i--)
        cout << d[i];
   }

    return 0;
}

数制转换
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>

using namespace std;
/*
*/
int main()
{
   int a,b,a1;
   char m[20],n[20];
   while (scanf("%d %s %d",&a,&m,&b)!=EOF)
   {
       int length = strlen(m);
       int m1 = 0;
       a1 = 1;  // 各位初始化权重为1
       for (int i = length-1;i>=0;i--)
       {
           int x;
           if (m[i] >= '0' && m[i] <= '9')
             x = m[i] - '0';
           else if (m[i] >= 'a' && m[i] <= 'z')
             x = m[i] - 'a' + 10;
           else if (m[i] >= 'A' && m[i] <= 'Z')
             x = m[i] - 'A' + 10;
           m1 += x*a1;
           a1 *= a;
       }
       int size = 0;
       while (m1>0)
       {
           int x = m1%b;
           n[size++] = (x<10)?x+'0' : x-10+'A';
           m1 /= b;
       }
       for (int i =size-1;i>=0;i--)
        cout << n[i];
       cout <<endl;
   }
    return 0;
}

gcd lcd
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>

using namespace std;
/*
*/

int gcd(int a,int b)
{
    if (b == 0)
        return a;
    else
        return gcd(b,a%b);
}
int main()
{
   int a,b;
   while (cin >> a >> b)
   {
          cout << gcd(a,b) << endl;
   }
    return 0;
}
 // 最小公倍数:a*b / gcd(a,b)
素数筛法
素数判定
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>

using namespace std;

int judge(int n)
{
    if (n ==1)
        return 0;
    if (n == 2)
        return 1;
    for (int i = 2; i <= sqrt(n)+1;i++)
    {
        if (n%i == 0) // i为N的一个除1和自身以外的公因数,则不是素数
            return 0;
    }
    return 1;

}
int main()
{
   int n ;
   while (cin >> n)
   {
       if (judge(n))
        cout << "yes" <<endl;
       else
        cout << "no" << endl;
   }
    return 0;
}

素数
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>

using namespace std;
// 把2-n之间所有的素数找到,在main中判断是否个位为1
int prime[10000]; // 存放找到的素数
bool isprime[10000];// 判断是否是素数
int primesize = 0;
void judge(int n)
{
    for (int i = 1;i<=n;i++)
        isprime[i] = false ; // 未判断

    for (int i =2;i<n;i++)
    {
        // 从2开始,因为2本身就是素数
        if (isprime[i]  == true ) // 被标记成非素数
            continue;
        prime[primesize++] = i; // 为false时加入到prime素数数组
        // 把素数的因数都标记为true
        for (int j = i*i ; j<=n;j = j+i) // 为什么从i*i开始
            isprime[j] = true;

    }
}
int main()
{
   int n ;
   bool output = false;
   while (cin >> n)
   {
       judge(n);
       for (int i = 0;i<primesize;i++)
       {
           if (prime[i]%10 == 1)
           {
               if (output == false)
               {
                   output = true;
                   cout << prime[i];
               }
               else
                   cout <<" "<< prime[i];
           }
       }
       cout <<endl;
   }
    return 0;
}

Prime Number // 求1-10000内第K个素数
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>

using namespace std;
// 把2-n之间所有的素数找到,在main中判断是否个位为1
int prime[100001]; // 存放找到的素数
int isprime[100001];// 判断是否是素数
int primesize = 0;
void judge(int n)
{
    for (int i = 1;i<=n;i++)
        isprime[i] = false ; // 未判断

    for (int i =2;i<n;i++)
    {
        // 从2开始,因为2本身就是素数
        if (isprime[i]  == true ) // 被标记成非素数
            continue;
        prime[primesize++] = i; // 为false时加入到prime素数数组
        // 把素数的因数都标记为true
        for (int j = i*i ; j<=n;j = j+i) // 为什么从i*i开始
            isprime[j] = true;

    }
}
int main()
{
   int k ;
   judge(100000);
   while (cin >> k)
   {
       cout << prime[k-1] << endl;
   }


    return 0;
}

####分解素因数

考虑N的取值范围是109,但是如果设成109的数组则内存空间不足,所以仅测试1-100000内的素数是否为N的素因数,如果N很大,还有一个大于100000的素因数则加一即可,因为大于100000的素因数最多只能有一个,两个就炸了INT了。

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>

using namespace std;
int prime[100001] ;
bool isprime[100001];
int primesize = 0;
void judge(int n)
{
    for (int i =0;i<=n;i++)
        isprime[i] = false;

    for (int i = 2;i<n;i++)
    {
        if (isprime[i] == true)
            continue;
        prime[primesize++] = i;
        for (int j = i*i;j<n;j=j+i)
            isprime[j] = true;
    }
}
int main()
{
   int n ;
   int e[100]={0},p[100]; //存放N的质因数以及指数
   int k = 0;
   while (cin >> n)
   {
       judge(100000);
       int number = 0 ;
       for (int i = 0;i<primesize;i++)
       {
           if (n%prime[i] == 0)
            p[k] = i;
           else
            continue;

           while (n%prime[i] == 0)
           {
               e[k] ++;
               n = n/prime[i];
           }
           k++;
       }
       for (int i =0;i<k;i++)
        number += e[i];
        if (n!=1) // N的取值范围是10^9,若测试完100000内的素数仍不能被除尽,则说明有一个大于100000的素数
            number ++;
       cout << number << endl;

   }
    return 0;
}

整除问题(超难数学题)
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>

using namespace std;
int prime[1010] ;
bool isprime[1010];
int primesize = 0;
// 为什么是1000以内的素数?因为a的取值范围是1-1000,故a没有超过1000的素因数
// 而N!能整除a,说明N!的素因数和a的素因数必定相同
void judge(int n)
{
    for (int i =0;i<=n;i++)
        isprime[i] = false;

    for (int i = 2;i<n;i++)
    {
        if (isprime[i] == true)
            continue;
        prime[primesize++] = i;
        for (int j = i*i;j<n;j=j+i)
            isprime[j] = true;
    }
}
int cnt[1010] ;// n!进行素因数分解后,对应prime[i]的素数的幂指数,可能为0
int cnt2[1010] ; //a的因子数
int main()
{
   int n ,a;
   int k ;
   while (cin>> n >>a)
   {
      judge(1000);
      for (int i =0;i<primesize;i++)
        cnt[i] =  cnt2[i] = 0; // 初始化两个计数器

      for (int i=0;i<primesize;i++)
      {
          // 对n!分解素因数,遍历到0-1000的每一个素数,
          int t = n;
          while (t)
          {
              cnt[i]+=t/prime[i];
              t = t/prime[i];
          }
      }
      int ans = 100000000;
      for (int i=0;i<primesize;i++)
      {
          while (a%prime[i] == 0)
          {
              cnt2[i]++;
              a/=prime[i];
          }
          if (cnt2[i] == 0)
            continue;//没有该素数则跳过,否则容易影响整除

          if (cnt[i]/cnt2[i]<ans )
            ans = cnt[i]/cnt2[i]; // 每计算出一个a的因数指数就和N!的比较一下
      }
      cout <<ans <<endl;
   }
    return 0;
}

二分求幂
人见人爱A^B
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>

using namespace std;

int main()
{
   int a,b;
   while (cin>>a>>b)
   {
       if (a==0 && b==0)
        break;
       int ans = 1;//最终结果变量
       while (b!=0)
       {
           if (b%2==1)
           {
               ans *= a; // ans 累乘a
               ans%=1000; // ans仅取后三位
           }
           b/=2;
           a = a*a;//求下一位二进制位的权重
           a %= 1000;//求a的后三位
       }
       cout << ans << endl;
   }
    return 0;
}

A sequence of numbers

10 min

#include<stdio.h>
#define ret 200907
long long cal(long long a,long long q,int k){
    long long ans=a;
    k--;
    while( k > 0){
        if(k%2==1){
            ans = (ans * q) % ret;
        }
        k/=2;
        q= (q*q)%ret;
    }
    return ans;
}
int main(){
    int n;
    scanf("%d",&n);
    for(int i=0;i<n;i++){
        long long a,b,c,ans; // a,b,c取值范围为0-2^64,long long 为64位的
        int k; // 10^9 int 足矣
        scanf("%lld%lld%lld%d",&a,&b,&c,&k);
        if(b-a==c-b)
            ans=(a%ret+(k-1)*((b-a)%ret))%ret; // (a+b)%c = (a%c +b%c)%c ,防止(a+b)溢出问题
        else{
            long long q=b/a;
            ans=cal(a,q,k);
        }
        printf("%lld\n",ans);
    }
    return 0;
}

高精度整数
a+b

超开心的是这道题我独立做出来了!虽然耗时很久,但自己思考比不停看别人的代码要强的多!

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>

using namespace std;

/*
a + b 位数不超过1000位,大整数,不能用基本数据类型存储,必须用字符串或者数组的形式
12354484 324645
time : 20+20+20+20+20 = 1h 45 min 

笔记: 
1. 数组的初始化方式:
int b[10]={0};  
但是如果是: int b[10] = {1} , 却只有第一个元素被初始化为1,其余仍为0

或者:
int a[size] ; 
memset(a,0,sizeof(int)*size); 对某指针指向的内存进行赋值,全部赋值为0

2. 结构体的初始化方式:
X x1 = { 1,2.2, 'c' };
X x2[3] = { {1, 1.1, 'a'}, {2, 2.2, 'b'}}; 使用大括号中嵌套大括号的方式

3. 对齐输出0000
%0xd // x为输出的整数宽度

*/
struct bigInteger {
int digit[300];
int size; // 该大整数的位数
}; // 每四位数字保存到一个数组里

int cal(char s1[1010],int i,int n)
{
    // s1[i] - s1[i-n+1]变为整数,循环N次
    int ans = 0;
    int r = 1;
    for (int j=0;j<n;j++)
    {
        ans += (s1[i]-'0')*r;
        i--;
        r *= 10;
    }
    return ans;
}

void print(bigInteger a)
{
    // 输出的要求很严格:非第一个数组则补齐四位
    printf("%d",a.digit[a.size-1]);
    for (int i = a.size-2;i>=0;i--)
    {
        printf("%04d",a.digit[i]);
    }
    cout << endl;

}
void init(bigInteger &a,char s[],int len)
{
    int i;
    if (len >= 4)
    {
        for (i = len-1;i>=3;i = i-4)
            a.digit[a.size++] = cal(s,i,4);
        // 如果字符串不正好是4的倍数,开头剩余必小于4
        if (i!=-1)
        {
          a.digit[a.size++] = cal(s,i,i+1);
        }
    }
    else
        a.digit[a.size++] = cal(s,len-1,len);
}
int main()
{
    bigInteger a={{0},0},b = {{0},0},c = {{0},0};
    int i;
    /* 1. 如何把很长的字符串输入到数组中
     输入到两个字符数组中,从size-1开始每四位字符形成一个整数,存放到数组中,
     从0开始倒着往数组中放,输出的时候从size反着输出即可
    */
    char s1[1010],s2[1010];
    int len1,len2;
    while (scanf("%s %s",s1,s2)!=EOF)
    {
        // 初始化为0,这样后面的相加部分才不用分长短讨论
        a={{0},0};b = {{0},0};c = {{0},0};
        len1 = strlen(s1);
        len2 = strlen(s2);
        init(a,s1,len1);
        init(b,s2,len2);
        // 把两部分相加,从数组0号开始递增,大于10000,截断第五位,加到下一个数组
        int add = 0,len = (a.size >= b.size) ? a.size : b.size;// 进位
        for (i = 0;i<len;i++)
        {
            int temp = a.digit[i] + b.digit[i] + add;
            add = temp/10000;
            c.digit[c.size++] = temp%10000;
        }
     //   print(a);
     //   print(b);
        print(c);

    }

    return 0;
}

N的阶乘

39 min

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <algorithm>

using namespace std;

struct bigInteger
{
    int digit[1001];  // 1000 !  < 1000^1000,每四位存储一个
    int size; // digit的长度
}a = {{0},0};

void print()
{
    // 找到不为0的第一位
    for (int i = 1 ;i<=1001;i++)
    {
        if (a.digit[i]!=0 && a.digit[i+1] == 0)
        {
            a.size = i;
            break;
        }

    }
    // i 指向最后一位

    printf("%d",a.digit[a.size]);
    for (int i = a.size-1; i >=1 ;i--)
        printf("%04d",a.digit[i]);
    cout << endl;
}
int main()
{
    int n;
    while (cin>>n)
    {
        a = {{0},0};
        int c = 0;
        a.digit[++a.size] = 1; // digit 从size=1 开始记录
        for (int i = 2 ;i<=n;i++)
        {
            for (int j = 1;j<=1000;j++) // digit数组中的每个元素都要乘以乘数
            {
                a.digit[j] = (a.digit[j]*i + c);
                int temp = a.digit[j];
                c = a.digit[j]/10000;
                a.digit[j] %= 10000;
                // size什么时候增加?每一位可能会产生无数次向前的进位
            }
        }
        print();
    }

    return 0;
}

####浮点数加法

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <algorithm>

using namespace std;

/*
浮点数从小数点进行分割,一个字符串分割成整数和小数数组,
但小数是左对齐,整数是右对齐。加完小数之后的进位和整数相加
*/

struct bigInteger
{
    int digit[1001];
    int size;
    int point;
}a,b,c;

int cal(char s[],int i,int n)
{
    int sum = 0;
    int c = 1;
    for (int j = 0 ; j < n ;j++)
    {
        sum += (s[i--]-'0')*c;
        c *= 10;
    }
    return sum;
}
void init(char s[],bigInteger &a)
{
    int len = strlen(s);
    // 找到小数点,记录位置并删除
    int i;
    for (i = 0;i<len;i++)
    {
        if (s[i] == '.')
        {
            a.point = i;
            break;
        }
    }
    for (i; i < len;i++)
    {
        s[i] = s[i+1];
    }
    for (i = len-2; i >= 3 ;i -= 4)
    {
        a.digit[++a.size] = cal(s,i,4);
    }
    if (i != -1)
    {
     // 不是4的倍数
        a.digit[++a.size] = cal(s,i,i+1);
    }
}
void print(bigInteger a)
{
    int i;
    printf("%d",a.digit[a.size]);
    for (i = a.size-1 ; i >=1 ;i--)
    {
        printf("%04d",a.digit[i]);
    }
    cout  << endl;
}
int main()
{
    int len1,len2,len;
    char s1[1001],s2[1001];
    while (scanf("%s %s",s1,s2)!=EOF)
    {
        // 初始化biginteger结构体
        init(s1,a);
        init(s2,b);

        print(a);
        print(b);

    }


    return 0;
}

二分求幂 问题重做 20min

过程推演了一会儿,代码的编写比较简单,主要是把过程弄懂

#include <iostream>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <queue>
#include <vector>

using namespace std;



int main()
{
    int a,b;
    while (cin>>a>>b)
    {
        if (a == 0 && b == 0)
            break;
        int ans = 1; int r = 0; // b对2的余数
        int t = a; // a的平方
        while (b>0)
        {
            r = b%2;
            b = b/2;

            if (r == 1)
            {
                ans = (ans * t)%1000;
            }
            t = (t*t)%1000;
        }
        cout << ans << endl;

    }

    return 0;
}

Tr
#include <iostream>
#include <stdio.h>
#include <stdlib.h>

using namespace std;
const int ret = 9973;
void cal(int a[11][11],int b[11][11],int n,int c[][11])
{

    int i,j,k;
    for (i=1;i<11;i++)
        for (j=1;j<11;j++)
        c[i][j] = 0;
    for (i = 1 ; i<=n;i++)
    {
        for (j=1;j<=n;j++)
        {
            for (k = 1 ; k <= n ;k++)
            {
              c[i][j] += a[i][k]*b[k][j];
            }

        }
    }
}
void equal(int ans[][11],int tmp[][11])
{
    int i,j;
    for (i=1;i<11;i++)
        for (j=1;j<11;j++)
    {
        ans[i][j] = tmp[i][j];
    }
}
int main()
{
    int t,i,j,n,k,z;
    int a[11][11];
    while (cin >> t)
    {
    for (z = 0;z<t;z++)
    {
        cin >> n >> k;
        for (i = 1;i<n+1;i++)
            for (j = 1;j<n+1;j++)
            cin >> a[i][j];

        int ans[11][11] =
        {1,0,0,
         0,1,0,
         0,0,1
        };
        int tmp[11][11];
        while (k>0)
        {
            if (k%2 == 1)
            {
              cal(ans,a,n,tmp);
              equal(ans,tmp);
            }
            k = k/2;
            //a = a * a;
            cal(a,a,n,tmp);
            equal(a,tmp);
        }
        int c = 0;
        for (i  = 1 ;i<=n;i++)
        {
           c += ans[i][i];
        }
        cout << c <<endl;
    }
    }
    return 0 ;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值