课程设计A实验报告数学3班付荣2018212805

  1. 题意: 当n在(x,y)范围内取整数值时,判定表达式n^2+n+41的值是否都为素数。

解题思路:将表达式的各个值储存在一个数组里面,再判断是否都为素数。

细节处理:当x和y同时为0时,不进行循环,应用break函数来实现。素数的判断这个细节是通过循环来实现的,并且应用了类于bool的判断(int a=0),来输出一个结果,并非多个结果。

判断素数方法 枚举当前2 到 本身的前一个 是否有能除尽的元素 若有 则不是素数 无 则是

可以优化到 根号下本身 因为 两个因子是重复的

源码:

#include<iostream>

#include<iomanip>

using namespace std;

int main()

{

    int x, y, i, n, t, j;

    int a[100];

    while (cin >> x >> y)

    {

        if (x == 0 && y == 0)

            break;

        i = 0;

        for (n = x; n <= y; n++)

        {

            a[i] = n*n + n + 41;

            i++;

        }

        int s = 0;

        t = y - x;

        for (i = 0; i <= t; i++)

        {

            for (j = 2; j < a[i]; j++)

            {

                if (a[i] % j == 0)

                {

                    s++;

                    break;

                }

               

            }

        }

        if (s == 0)

            cout << "OK" << endl;

        else

            cout << "Sorry" << endl;

总结:素数是程序中经常考察的知识点,明白素数的定义,理清思路。

 

2.题意:输出集合A-集合B的差

解题思路:本题本质是枚举集合A的每一个元素,看集合B中是否有相同元素。如果有,就去掉,如果没有就保留输出。

细节处理:当集合A和集合B中元素个数为0时,应用break函数结束程序;判断完A中有无B的元素之后,将那个元素a[j]标记,最后输出时去掉或者判断最后是否为空集。

源码:

#include<iostream>

#include<algorithm>

using namespace std;

int a[110];

int b[110];

int main()

{

    int n,m;

    while(cin>>n>>m,!(n==0&m==0))

    {

        int k=0;

        for(int i=1;i<=n;i++)

           cin>>a[i];

        for(int i=1;i<=m;i++)

           cin>>b[i];

        for(int i=1;i<=m;i++)

        {

            for(int j=1;j<=n;j++)

            {

 

                if(b[i]==a[j])

                  a[j]=0;

            }

        }

        sort(a,a+n+1);

        for(int i=1;i<=n;i++)

        {

            if(a[i]!=0)

            {

                cout<<a[i]<<" ";

                k++;

            }

        }

        if(k==0)

          cout<<"NULL";

        cout<<endl;

    }

    return 0;

}

感想:数学基本知识点很重要,有时候应用sort等函数会简单很多。

  但是这个题不能应用sort 因为最后还要按照原来的顺序输出

本来想用sort 省时间

 

  1. 题意:有一头牛每年年初生一头小母牛并且小牛从第四个年头开始,每年年初也生一头小牛。第N年会有多少牛。

解题思路:这个题类似斐波那契数列(找规律题)。这个题的规律是:F(N)=F(N-1)+F(N-3)。因为每年的牛可以分为两批,第一批是上一年的牛,另一批是新生代的牛。上一年的牛是直接继承的,新生代的牛的来源是前前年的牛所生,所以加上前前年的数量。

细节处理:这个题前四年需要特判:a【1】=1;a【2】=2;a【3】=3;a【4】=4,从第五年开始循环跑数据。

 

源码:

 

#include<iostream>

#include<iomanip>

using namespace std;

int main()

{

   int n, i;

   long long a[100];

   while(cin>>n)

   {

       if(n==0)

       break;

       a[1]=1;

       a[2]=2;

       a[3]=3;

       a[4]=4;

       for(i=5;i<60;i++)

       {

           a[i]=a[i-1]+a[i-3];

       }

       cout<<a[n]<<endl;

   }

   return 0;

}

感悟:斐波那契数列经常出现在C语言程序设计中,做这类题只需要找出an和其他项的关系即可(细心和耐心)

  1. 题意:有一个定义为从2开始的递增有序偶数并且长度为n的数列,现按照顺序每m个数求出一个平均值,如果最后不足m个,则以实际数量求平均值。

解题思路:m m个数相加,根据题目要求来做,没有更好的思路。

细节处理:应用一个数组来储存每一个平均值,最后输出

源码:

#include<iostream>

using namespace std;

int main()

{

    int i,n,m;

    int a[1000];

    int b[1001];

    while(cin>>m>>n)

    {

        int x = 0;

        int s = 0;

        int sum = 0;

        for(int i = 1 ; i <= m;i++)

        {

            if (x == n)

            {

               x= 0;

               b[s++] = sum/n;

               sum = 0;

            }

            x++;

            sum += i*2;

        }

        if(sum!=0)

        b[s++] = sum/x;

        for(int i= 0 ; i<s;i++)

        {

            if(i == s-1)

                cout<<b[i]<<endl;

            else

                cout<<b[i]<<" ";

        }

    }

 

    return 0;

}

感悟:很多题找不到快捷方法,只能根据题的意思来进行编程,有耐心和细心,一定可以做出来的。

  1. 题意:至少需要准备多少张人民币,才能在给每位老师发工资的时候都不用找零

解题思路:根据题意思考可知,即从最大的开始选,才能保证最后需要的人民币数最少。

细节处理:应用整除和求余来进行计算。

源码:

#include<iostream>

using namespace std;

int main()

{

    int n,i,a[10000],b,c,d,e,f,g;

    while(cin>>n)

    {

        if(n==0)

        break;

        for(i=0;i<n;i++)

        cin>>a[i];

        int sum=0;

        for(i=0;i<n;i++)

        {

            b=a[i]/100;

            c=(a[i]%100)/50;

            d=(a[i]%100)%50/10;

            e=(a[i]%100)%50%10/5;

            f=(a[i]%100)%50%10%5/2;

            g=(a[i]%100)%50%10%5%2/1;

            sum=b+c+d+e+f+g+sum;

        }

        cout<<sum<<endl;

 

    }

    return 0;

}

6.题意:输入一个十进制数N,将它转换成R进制数输出。

解题思路:转化 R 进制的方法 :

用 十进制 为例

十进制是怎么区分每一位的

个位数 等于 N%10;

十位数 等于 减去个位数 然后 %100;

百位数 等于 减去百位数个位数 然后 %1000;

......

再说一个每个位数的数字代表了什么

十位数上的 数字 t

表示 个位数  t * 10 ;

也就是说 必须要有 t 个 10 才能变到 十位数的 t

对于每一个进制 也是同样的道理

比如现在有一个数

不管是什么进制(计算机中储存的所有数都是二进制的形式存储 然后补码的形式保存)

只要用了 / 号 绝对不会算错(都是补码运算)

给了你一个数 N

 

N%R   代表当前位数是多少

N/R   因为整形运算余数不保留 剩下的需要晋级 晋级的变为新的N

如果N等于0表明剩下的运算也结束了

更简单的思路是这样子想:

换成加法的形式:现在有 N个1要加起来变成一个R进制的 位数

第一位 逢R晋1,加着加着当前的位数变成一个小于 R的数

第二位 对上述晋升的位数 执行相同的操作即可

细节处理:R大于10时,需要考虑对应的数字规则(参考十六进制)

源码:

     #include<iostream>

using namespace std;

char frdsz(int x)

{

    if (x == 10)

        return 'A';

    if (x == 11)

        return 'B';

    if (x == 12)

        return 'C';

    if (x == 13)

        return 'D';

    if (x == 14)

        return 'E';

    if (x == 15)

        return 'F';

}

int main()

{

    int N, R;

    int a[100];

    int X;

    bool shifoufushu;

    while (cin >> N >> R)

    {

        X = 0;

        shifoufushu = 0;

        if (N < 0)

        {

            N = abs(N);

            shifoufushu = 1;

        }

        while (1)

        {

            if (N <= 0)

                break;

            a[X] = N % R;

            N = N / R;

            X++;

        }

        if (shifoufushu)

        {

            cout << "-";

        }

        for (int i = X - 1; i >= 0; i--)

        {

            if (a[i] >= 10)

                cout << frdsz(a[i]);

            else

               cout << a[i];

        }

        cout << endl;

 

    }

}

感想:联系计算机进制转化是要明白是怎么样子转化的,要思考然后再实践。

7. 题意:计算A+B,A和B都是由3个整数组成,分别表示时分秒。

解题思路:从秒开始加,如果多于60就把多的那一部分加到分上面去;分相加同理。

细节处理:将时分秒利用数组巧妙的储存。

源码:

     #include<iostream>

using namespace std;

int main()

{

    int i,n,m;

    int a[1000];

    int b[1001];

    int s[1001];

    cin >> n;

    while(n--)

  {

 

      for(int i= 0 ; i <3 ;i++)

        cin>>a[i];

      for(int j= 0 ; j < 3 ; j++)

        cin>>b[j];

     int jinwei=0;;

     for(int j = 2 ; j>=0;j--)

     {

           s[j] =a[j]+b[j]+jinwei;

           if(j != 0 && s[j]>=60)

           {

              jinwei = s[j]/60;

              s[j] = s[j]%60;

           }

           else

           {

               jinwei = 0;

           }

     }

     for(int i = 0;i<3;i++)

     {

         if(i == 2)

            cout<<s[i]<<endl;

         else

          cout<<s[i]<<" ";

     }

    }

    return 0;

}

感悟:实际问题实际分析,考虑实际再实践。

8.题意:有方程Ai = (Ai-1 + Ai+1)/2 - Ci ,给出A0, An+1, 和 C1, C2, .....Cn。计算A1 = ?

 解题思路:推导出递归方程,然后进行编程计算。

推导过程 是举特例

从 A4 开始 能枚举出规律

 细节处理:最后保留小数问题要记得保留,利用数组解决问题。

源码:

   #include<iostream>

#include<string.h>

#include<algorithm>

#include<string>

#include<iomanip>

using namespace std;

int main()

{

    double a[3002];

    double c[3002];

    int n;

    while(cin >> n)

    {

 

    cin >> a[0];

    cin >> a[n+1];

    for(int i= 0 ; i<n;i++)

     cin >> c[i];

    double a1 = a[0]*n + a[n+1];

    for(int i = 1; i<=n;i++)

         a1 -= 2.0*i*c[n-i];

    cout<<fixed<<setprecision(2)<<a1/(n+1)<<endl;

    }

}

感悟:关于数学方程题应在纸面上推出递推公式再进行编程。

9.题意:所有的短号都是是 6+手机号的后5位,给一个11位长的手机号码,找出对应的短号

解题思路:先输出一个6,在输出这个string的6—10位。

细节处理:字符串的处理

源码:

#include<iostream>

#include<string.h>

#include<algorithm>

#include<string>

using namespace std;

int main()

{

    int n;

    cin >> n;

    string t;

    while(n--)

    {

       cin >> t;

       cout<<"6";

       for(int i=6; i<11;i++)

        cout<<t[i];

        cout<<endl;

    }

}

感想:考虑输出格式规律使程序简化。

10.题意:求A^B的最后三位数表示的整数。

  解题思路:每次只算最后三位数。比如:6789,第一次6789*6789,只算789*789就行,789*789的结果%1000再平方,一直这么下去。

  源码:

#include<iostream>

#include<string.h>

#include<algorithm>

using namespace std;

int main()

{

    int n,m;

    while(cin>>n>>m)

    {

        if( n== 0 && m == 0)

            break;

        int sum = 1;

        while(m--)

        {

            sum = sum % 1000;

            sum *= n;

            //cout<< sum <<endl;

        }

        sum= sum % 1000;

        cout<< sum <<endl;

    }

}

11. 题意:判断给定的两个数是否是亲和数

解题思路:求出每一个数的真约数,再分别加起来,看是否是对方本身

源码:

#include<iostream>

using namespace std;

int main()

{

    int A,B,M,i,a[10000],b[10000];

    cin>>M;

    while(M--)

    {

        cin>>A>>B;

        int j=0,s=0;

        for(i=1;i<A;i++)

        {

            if(A%i==0)

           {

               a[j]=i;

               j++;

           }

        }

        for(i=1;i<B;i++)

        {

            if(B%i==0)

            {

            b[s]=i;

            s++;

            }

        }

        int s1=0,s2=0;

        for(i=0;i<=j-1;i++)

        {

            s1+=a[i];

        }

        for(i=0;i<=s-1;i++)

        {

            s2+=b[i];

        }

        if(A==s2&&B==s1)

        cout<<"YES"<<endl;

        else

        cout<<"NO"<<endl;

    }

    return 0;

}

12.题意:求买菜到底花了多少钱

思路:单价乘以斤数之后加起来

细节优化:由于是 四舍五入,所以最后加上一个 0.01输出,这是关键,因为计算机5舍6入,加上0.01就变成了四舍五入。

  源码:

#include<iostream>

#include<string.h>

#include<algorithm>

#include<string>

#include<iomanip>

using namespace std;

int main()

{

    double a[3002];

    double c[3002];

    int n;

    string t;

   double    sum = 0;

    while(cin >> t)

    {

    double n;

    double x;

    cin >> n;

    cin >> x;

    sum += n*x;

 

    }

    cout<<fixed<<setprecision(1)<<sum+0.01<<endl;

}

13.题意:有一只蜜蜂只能爬向右侧相邻的蜂房,不能反向爬行。请编程计算蜜蜂从蜂房a爬到蜂房b的可能路线数。

解题思路:写出递推公式ai=ai-1+ai-2

源码:

#include<iostream>

using namespace std;

 

int main()

{

    long long a[60];

    a[1] = 1;

    a[2] = 1;

    for (int i = 3; i <= 55; i++)

    {

        a[i] = a[i - 1] + a[i - 2];

    }

    int n;

    cin >> n;

    while (n--)

    {

        int t;

        int x;

        cin >> t >> x;

        int f = x - t;

        cout << a[f+1] << endl;

    }

}

  1. 2

题意 从两组数中找到最大的组合

思路

一开始错误的原因是任选一个女孩开始暴力枚举  根据女孩选男孩  最后tl 发现有很多相同的情况 比如 女孩 1  构成 1 2 女孩 2 构成 2 3  和 先女孩 2 3 女孩 1 2 是一样的效果 如果数据多样化的化 会有很多的重复情况  百度一下  如果 从头开始 只要任意一个女孩有分配的情况 就可以  比如 先枚举一个女孩 1 找到就返回

标记一下当前男孩指定的女孩为 1  (如果不标记 假设女孩3只能选男孩1 会造成 女孩1 占用了最优的位置 ) 枚举到下一个女孩

如果当前女孩 只能制定一个男孩 但是这个男孩又被别的女孩选了

那么这时 将这个男孩给这个女生 在标记一下这个男孩不能选 男孩一开始标记的女孩 再选一次  找到可以 找不到无所谓 反正这个题

是求个数 不是求匹配方案 这么for循环下了 祛除了很多重复情况

算法本义 匈牙利算法 二分图最大匹配算法

细节处理 

主要是 b数组记录了 当前男孩选中的女孩 不停地递归 知道找到 当前最适合的方案 尽量让 这个方案由最优值

源码 :

 

#include<iostream>

#include<string.h>

#include<algorithm>

#include<string>

#include<iomanip>

using namespace std;

int a[1000][1000];

bool boy[1000];

int ss[1000];

int K,M,N;

int minn = 0;

 

bool dfs(int x)

{

    for(int i=1;i<=N;i++)

    {

       if (a[x][i]&& boy[i]==0)

        {

            boy[i] = 1;

            if (ss[i]==0)

            {

                ss[i]=x;

                return true;

            }

            else if(dfs(ss[i]))

            {

                ss[i]=x;

                return true;

            }

        }

    }

    return false;

}

int main()

{

   int n;

   while(cin>>K)

   {

       if(K==0)

        break;

       memset(a,0,sizeof(a));

       memset(boy,0,sizeof(boy));

       memset(ss,0,sizeof(ss));

       cin>>M>>N;

       minn = 0;

       for(int i = 0; i < K;i++)

       {

           int g ,b;

           cin >> g >>b;

           a[g][b] = 1;

       }

       for(int i = 1 ; i <= M; i++)

       {

           memset(boy,0,sizeof(boy));

           if(dfs(i))

             minn++;

       }

       cout <<minn<<endl;

   }

}

 

15  

题意 小乌龟的题 动态规划(百度一下)

解题思路 : 完全没有 从网上找了一篇博客 这是一个动态规划题目

动态规划 定义 局部最优解 解决不了全局最优的问题 这也是数学的一种学法

通常与贪心算法一起定义

贪心算法从 局部最优推出全局最优解

这个题 dp【i】指的是从 开始的位置 到 i 位置的最优情况

也就是小乌龟到i位置的最优解

枚举时候 先从 1 开始 由于是加满油的状态 所以 第一个加油站是一个固定的值 有初值情况

然后开始 从 2 开始 枚举前面是否加油 如果是0 代表从 头开始到现在

如果是 1 代表从 1 加油 走到 2

比较两个大小 得到到2 点的最优情况

然后从 3 开始 枚举 0 1 2 点是否加油 如果 0点加油 就是 0的最优情况 加上后续的

1点加油 就是 1的最优情况 加上后续的 因为到1的最优情况已经确定

所以 只需要考虑在1点如果不加油的情况来

下面推广到 n

因为 n以前的最优值都已经确定了

到 n只有 几种情况

N-1 -加满油 - n

  1. 2 加满油 - n

N-3 加满油到 n

是不是 考虑 当前位置是否加油 那不用管 因为 n-2 的最优解已经确定 所以 n-3 不加油的话 不影响全局   但是如果n-3加油的话

N-2 不是最优解 但是 n-1 可能是 这就说明了 局部最优 解决不了全局最优

但是从局部最优的情况 逐步地推到全局最优

细节处理 如果当前时开始位置的话不用加上 加油时间

源码

#include<iostream>

#include<cmath>

#include<algorithm>

#include<string>

#include<string.h>

using namespace std;

 

int main()

{

    int L;

    int N, C, T;

    int VR, VT1, VT2;

    double NS[1000];

    double dp[1000];

    while (cin >> L)

    {

        cin >> N >> C >> T;

        cin >> VR >> VT1 >> VT2;

        for (int i = 1; i <= N; i++)

        {

            cin >> NS[i];

        }

        double time;

        int j;

    

        NS[0] = 0;

        NS[N + 1] = L;

        dp[0] = 0;

        for (int i = 1; i <= N+1; i++)

        {

            dp[i] = 1000000;

            for ( j = 0; j < i; j++)

            {

                if ((NS[i] - NS[j]) > C)

                {

                    time = 1.0*C / VT1 + 1.0*(NS[i] - NS[j] - C) / VT2;

                }

                else

                {

                    time = 1.0*(NS[i] - NS[j]) / VT1;

                }

                if (j>0)

                dp[i] = min(dp[i], dp[j] + time + T);

                else

                dp[i] = min(dp[i], dp[j] + time);

            }

            

        }

        double timer = 1.0*L / VR;

        if (timer > dp[N+1])

        {

            cout << "What a pity rabbit!" << endl;

        }

  1. 题意: 当n在(x,y)范围内取整数值时,判定表达式n^2+n+41的值是否都为素数。

解题思路:将表达式的各个值储存在一个数组里面,再判断是否都为素数。

细节处理:当x和y同时为0时,不进行循环,应用break函数来实现。素数的判断这个细节是通过循环来实现的,并且应用了类于bool的判断(int a=0),来输出一个结果,并非多个结果。

判断素数方法 枚举当前2 到 本身的前一个 是否有能除尽的元素 若有 则不是素数 无 则是

可以优化到 根号下本身 因为 两个因子是重复的

源码:

#include<iostream>

#include<iomanip>

using namespace std;

int main()

{

    int x, y, i, n, t, j;

    int a[100];

    while (cin >> x >> y)

    {

        if (x == 0 && y == 0)

            break;

        i = 0;

        for (n = x; n <= y; n++)

        {

            a[i] = n*n + n + 41;

            i++;

        }

        int s = 0;

        t = y - x;

        for (i = 0; i <= t; i++)

        {

            for (j = 2; j < a[i]; j++)

            {

                if (a[i] % j == 0)

                {

                    s++;

                    break;

                }

               

            }

        }

        if (s == 0)

            cout << "OK" << endl;

        else

            cout << "Sorry" << endl;

感想:素数的判断是C语言程序中常考的一个问题,应明白素数的定义,然后和程序结合起来。只输出一个最终结论时,应使用判断,防止多次输出。

  1. 题意:输出集合A-集合B的差

解题思路:本题本质是枚举集合A的每一个元素,看集合B中是否有相同元素。如果有,就去掉,如果没有就保留输出。

细节处理:当集合A和集合B中元素个数为0时,应用break函数结束程序;判断完A中有无B的元素之后,将那个元素a[j]标记,最后输出时去掉或者判断最后是否为空集。

源码:

#include<iostream>

#include<algorithm>

using namespace std;

int a[110];

int b[110];

int main()

{

    int n,m;

    while(cin>>n>>m,!(n==0&m==0))

    {

        int k=0;

        for(int i=1;i<=n;i++)

           cin>>a[i];

        for(int i=1;i<=m;i++)

           cin>>b[i];

        for(int i=1;i<=m;i++)

        {

            for(int j=1;j<=n;j++)

            {

 

                if(b[i]==a[j])

                  a[j]=0;

            }

        }

        sort(a,a+n+1);

        for(int i=1;i<=n;i++)

        {

            if(a[i]!=0)

            {

                cout<<a[i]<<" ";

                k++;

            }

        }

        if(k==0)

          cout<<"NULL";

        cout<<endl;

    }

    return 0;

}

感想:数学基本知识点很重要,有时候应用sort等函数会简单很多。

  但是这个题不能应用sort 因为最后还要按照原来的顺序输出

本来想用sort 省时间

 

  1. 题意:有一头牛每年年初生一头小母牛并且小牛从第四个年头开始,每年年初也生一头小牛。第N年会有多少牛。

解题思路:这个题类似斐波那契数列(找规律题)。这个题的规律是:F(N)=F(N-1)+F(N-3)。因为每年的牛可以分为两批,第一批是上一年的牛,另一批是新生代的牛。上一年的牛是直接继承的,新生代的牛的来源是前前年的牛所生,所以加上前前年的数量。

细节处理:这个题前四年需要特判:a【1】=1;a【2】=2;a【3】=3;a【4】=4,从第五年开始循环跑数据。

 

源码:

 

#include<iostream>

#include<iomanip>

using namespace std;

int main()

{

   int n, i;

   long long a[100];

   while(cin>>n)

   {

       if(n==0)

       break;

       a[1]=1;

       a[2]=2;

       a[3]=3;

       a[4]=4;

       for(i=5;i<60;i++)

       {

           a[i]=a[i-1]+a[i-3];

       }

       cout<<a[n]<<endl;

   }

   return 0;

}

感悟:斐波那契数列经常出现在C语言程序设计中,做这类题只需要找出an和其他项的关系即可(细心和耐心)

  1. 题意:有一个定义为从2开始的递增有序偶数并且长度为n的数列,现按照顺序每m个数求出一个平均值,如果最后不足m个,则以实际数量求平均值。

解题思路:m m个数相加,根据题目要求来做,没有更好的思路。

细节处理:应用一个数组来储存每一个平均值,最后输出

源码:

#include<iostream>

using namespace std;

int main()

{

    int i,n,m;

    int a[1000];

    int b[1001];

    while(cin>>m>>n)

    {

        int x = 0;

        int s = 0;

        int sum = 0;

        for(int i = 1 ; i <= m;i++)

        {

            if (x == n)

            {

               x= 0;

               b[s++] = sum/n;

               sum = 0;

            }

            x++;

            sum += i*2;

        }

        if(sum!=0)

        b[s++] = sum/x;

        for(int i= 0 ; i<s;i++)

        {

            if(i == s-1)

                cout<<b[i]<<endl;

            else

                cout<<b[i]<<" ";

        }

    }

 

    return 0;

}

感悟:很多题找不到快捷方法,只能根据题的意思来进行编程,有耐心和细心,一定可以做出来的。

  1. 题意:至少需要准备多少张人民币,才能在给每位老师发工资的时候都不用找零

解题思路:根据题意思考可知,即从最大的开始选,才能保证最后需要的人民币数最少。

细节处理:应用整除和求余来进行计算。

源码:

#include<iostream>

using namespace std;

int main()

{

    int n,i,a[10000],b,c,d,e,f,g;

    while(cin>>n)

    {

        if(n==0)

        break;

        for(i=0;i<n;i++)

        cin>>a[i];

        int sum=0;

        for(i=0;i<n;i++)

        {

            b=a[i]/100;

            c=(a[i]%100)/50;

            d=(a[i]%100)%50/10;

            e=(a[i]%100)%50%10/5;

            f=(a[i]%100)%50%10%5/2;

            g=(a[i]%100)%50%10%5%2/1;

            sum=b+c+d+e+f+g+sum;

        }

        cout<<sum<<endl;

 

    }

    return 0;

}

6.题意:输入一个十进制数N,将它转换成R进制数输出。

解题思路:转化 R 进制的方法 :

用 十进制 为例

十进制是怎么区分每一位的

个位数 等于 N%10;

十位数 等于 减去个位数 然后 %100;

百位数 等于 减去百位数个位数 然后 %1000;

......

再说一个每个位数的数字代表了什么

十位数上的 数字 t

表示 个位数  t * 10 ;

也就是说 必须要有 t 个 10 才能变到 十位数的 t

对于每一个进制 也是同样的道理

比如现在有一个数

不管是什么进制(计算机中储存的所有数都是二进制的形式存储 然后补码的形式保存)

只要用了 / 号 绝对不会算错(都是补码运算)

给了你一个数 N

 

N%R   代表当前位数是多少

N/R   因为整形运算余数不保留 剩下的需要晋级 晋级的变为新的N

如果N等于0表明剩下的运算也结束了

更简单的思路是这样子想:

换成加法的形式:现在有 N个1要加起来变成一个R进制的 位数

第一位 逢R晋1,加着加着当前的位数变成一个小于 R的数

第二位 对上述晋升的位数 执行相同的操作即可

细节处理:R大于10时,需要考虑对应的数字规则(参考十六进制)

源码:

     #include<iostream>

using namespace std;

char frdsz(int x)

{

    if (x == 10)

        return 'A';

    if (x == 11)

        return 'B';

    if (x == 12)

        return 'C';

    if (x == 13)

        return 'D';

    if (x == 14)

        return 'E';

    if (x == 15)

        return 'F';

}

int main()

{

    int N, R;

    int a[100];

    int X;

    bool shifoufushu;

    while (cin >> N >> R)

    {

        X = 0;

        shifoufushu = 0;

        if (N < 0)

        {

            N = abs(N);

            shifoufushu = 1;

        }

        while (1)

        {

            if (N <= 0)

                break;

            a[X] = N % R;

            N = N / R;

            X++;

        }

        if (shifoufushu)

        {

            cout << "-";

        }

        for (int i = X - 1; i >= 0; i--)

        {

            if (a[i] >= 10)

                cout << frdsz(a[i]);

            else

               cout << a[i];

        }

        cout << endl;

 

    }

}

感想:联系计算机进制转化是要明白是怎么样子转化的,要思考然后再实践。

7. 题意:计算A+B,A和B都是由3个整数组成,分别表示时分秒。

解题思路:从秒开始加,如果多于60就把多的那一部分加到分上面去;分相加同理。

细节处理:将时分秒利用数组巧妙的储存。

源码:

     #include<iostream>

using namespace std;

int main()

{

    int i,n,m;

    int a[1000];

    int b[1001];

    int s[1001];

    cin >> n;

    while(n--)

  {

 

      for(int i= 0 ; i <3 ;i++)

        cin>>a[i];

      for(int j= 0 ; j < 3 ; j++)

        cin>>b[j];

     int jinwei=0;;

     for(int j = 2 ; j>=0;j--)

     {

           s[j] =a[j]+b[j]+jinwei;

           if(j != 0 && s[j]>=60)

           {

              jinwei = s[j]/60;

              s[j] = s[j]%60;

           }

           else

           {

               jinwei = 0;

           }

     }

     for(int i = 0;i<3;i++)

     {

         if(i == 2)

            cout<<s[i]<<endl;

         else

          cout<<s[i]<<" ";

     }

    }

    return 0;

}

感悟:实际问题实际分析,考虑实际再实践。

8.题意:有方程Ai = (Ai-1 + Ai+1)/2 - Ci ,给出A0, An+1, 和 C1, C2, .....Cn。计算A1 = ?

 解题思路:推导出递归方程,然后进行编程计算。

推导过程 是举特例

从 A4 开始 能枚举出规律

 细节处理:最后保留小数问题要记得保留,利用数组解决问题。

源码:

   #include<iostream>

#include<string.h>

#include<algorithm>

#include<string>

#include<iomanip>

using namespace std;

int main()

{

    double a[3002];

    double c[3002];

    int n;

    while(cin >> n)

    {

 

    cin >> a[0];

    cin >> a[n+1];

    for(int i= 0 ; i<n;i++)

     cin >> c[i];

    double a1 = a[0]*n + a[n+1];

    for(int i = 1; i<=n;i++)

         a1 -= 2.0*i*c[n-i];

    cout<<fixed<<setprecision(2)<<a1/(n+1)<<endl;

    }

}

感悟:关于数学方程题应在纸面上推出递推公式再进行编程。

9.题意:所有的短号都是是 6+手机号的后5位,给一个11位长的手机号码,找出对应的短号

解题思路:先输出一个6,在输出这个string的6—10位。

细节处理:字符串的处理

源码:

#include<iostream>

#include<string.h>

#include<algorithm>

#include<string>

using namespace std;

int main()

{

    int n;

    cin >> n;

    string t;

    while(n--)

    {

       cin >> t;

       cout<<"6";

       for(int i=6; i<11;i++)

        cout<<t[i];

        cout<<endl;

    }

}

感想:考虑输出格式规律使程序简化。

10.题意:求A^B的最后三位数表示的整数。

  解题思路:每次只算最后三位数。比如:6789,第一次6789*6789,只算789*789就行,789*789的结果%1000再平方,一直这么下去。

  源码:

#include<iostream>

#include<string.h>

#include<algorithm>

using namespace std;

int main()

{

    int n,m;

    while(cin>>n>>m)

    {

        if( n== 0 && m == 0)

            break;

        int sum = 1;

        while(m--)

        {

            sum = sum % 1000;

            sum *= n;

            //cout<< sum <<endl;

        }

        sum= sum % 1000;

        cout<< sum <<endl;

    }

}

11. 题意:判断给定的两个数是否是亲和数

解题思路:求出每一个数的真约数,再分别加起来,看是否是对方本身

源码:

#include<iostream>

using namespace std;

int main()

{

    int A,B,M,i,a[10000],b[10000];

    cin>>M;

    while(M--)

    {

        cin>>A>>B;

        int j=0,s=0;

        for(i=1;i<A;i++)

        {

            if(A%i==0)

           {

               a[j]=i;

               j++;

           }

        }

        for(i=1;i<B;i++)

        {

            if(B%i==0)

            {

            b[s]=i;

            s++;

            }

        }

        int s1=0,s2=0;

        for(i=0;i<=j-1;i++)

        {

            s1+=a[i];

        }

        for(i=0;i<=s-1;i++)

        {

            s2+=b[i];

        }

        if(A==s2&&B==s1)

        cout<<"YES"<<endl;

        else

        cout<<"NO"<<endl;

    }

    return 0;

}

12.题意:求买菜到底花了多少钱

思路:单价乘以斤数之后加起来

细节优化:由于是 四舍五入,所以最后加上一个 0.01输出,这是关键,因为计算机5舍6入,加上0.01就变成了四舍五入。

  源码:

#include<iostream>

#include<string.h>

#include<algorithm>

#include<string>

#include<iomanip>

using namespace std;

int main()

{

    double a[3002];

    double c[3002];

    int n;

    string t;

   double    sum = 0;

    while(cin >> t)

    {

    double n;

    double x;

    cin >> n;

    cin >> x;

    sum += n*x;

 

    }

    cout<<fixed<<setprecision(1)<<sum+0.01<<endl;

}

13.题意:有一只蜜蜂只能爬向右侧相邻的蜂房,不能反向爬行。请编程计算蜜蜂从蜂房a爬到蜂房b的可能路线数。

解题思路:写出递推公式ai=ai-1+ai-2

源码:

#include<iostream>

using namespace std;

 

int main()

{

    long long a[60];

    a[1] = 1;

    a[2] = 1;

    for (int i = 3; i <= 55; i++)

    {

        a[i] = a[i - 1] + a[i - 2];

    }

    int n;

    cin >> n;

    while (n--)

    {

        int t;

        int x;

        cin >> t >> x;

        int f = x - t;

        cout << a[f+1] << endl;

    }

}

  1. 2

题意 从两组数中找到最大的组合

思路

一开始错误的原因是任选一个女孩开始暴力枚举  根据女孩选男孩  最后tl 发现有很多相同的情况 比如 女孩 1  构成 1 2 女孩 2 构成 2 3  和 先女孩 2 3 女孩 1 2 是一样的效果 如果数据多样化的化 会有很多的重复情况  百度一下  如果 从头开始 只要任意一个女孩有分配的情况 就可以  比如 先枚举一个女孩 1 找到就返回

标记一下当前男孩指定的女孩为 1  (如果不标记 假设女孩3只能选男孩1 会造成 女孩1 占用了最优的位置 ) 枚举到下一个女孩

如果当前女孩 只能制定一个男孩 但是这个男孩又被别的女孩选了

那么这时 将这个男孩给这个女生 在标记一下这个男孩不能选 男孩一开始标记的女孩 再选一次  找到可以 找不到无所谓 反正这个题

是求个数 不是求匹配方案 这么for循环下了 祛除了很多重复情况

算法本义 匈牙利算法 二分图最大匹配算法

细节处理 

主要是 b数组记录了 当前男孩选中的女孩 不停地递归 知道找到 当前最适合的方案 尽量让 这个方案由最优值

源码 :

 

#include<iostream>

#include<string.h>

#include<algorithm>

#include<string>

#include<iomanip>

using namespace std;

int a[1000][1000];

bool boy[1000];

int ss[1000];

int K,M,N;

int minn = 0;

 

bool dfs(int x)

{

    for(int i=1;i<=N;i++)

    {

       if (a[x][i]&& boy[i]==0)

        {

            boy[i] = 1;

            if (ss[i]==0)

            {

                ss[i]=x;

                return true;

            }

            else if(dfs(ss[i]))

            {

                ss[i]=x;

                return true;

            }

        }

    }

    return false;

}

int main()

{

   int n;

   while(cin>>K)

   {

       if(K==0)

        break;

       memset(a,0,sizeof(a));

       memset(boy,0,sizeof(boy));

       memset(ss,0,sizeof(ss));

       cin>>M>>N;

       minn = 0;

       for(int i = 0; i < K;i++)

       {

           int g ,b;

           cin >> g >>b;

           a[g][b] = 1;

       }

       for(int i = 1 ; i <= M; i++)

       {

           memset(boy,0,sizeof(boy));

           if(dfs(i))

             minn++;

       }

       cout <<minn<<endl;

   }

}

 

15  

题意 小乌龟的题 动态规划(百度一下)

解题思路 : 完全没有 从网上找了一篇博客 这是一个动态规划题目

动态规划 定义 局部最优解 解决不了全局最优的问题 这也是数学的一种学法

通常与贪心算法一起定义

贪心算法从 局部最优推出全局最优解

这个题 dp【i】指的是从 开始的位置 到 i 位置的最优情况

也就是小乌龟到i位置的最优解

枚举时候 先从 1 开始 由于是加满油的状态 所以 第一个加油站是一个固定的值 有初值情况

然后开始 从 2 开始 枚举前面是否加油 如果是0 代表从 头开始到现在

如果是 1 代表从 1 加油 走到 2

比较两个大小 得到到2 点的最优情况

然后从 3 开始 枚举 0 1 2 点是否加油 如果 0点加油 就是 0的最优情况 加上后续的

1点加油 就是 1的最优情况 加上后续的 因为到1的最优情况已经确定

所以 只需要考虑在1点如果不加油的情况来

下面推广到 n

因为 n以前的最优值都已经确定了

到 n只有 几种情况

N-1 -加满油 - n

  1. 2 加满油 - n

N-3 加满油到 n

是不是 考虑 当前位置是否加油 那不用管 因为 n-2 的最优解已经确定 所以 n-3 不加油的话 不影响全局   但是如果n-3加油的话

N-2 不是最优解 但是 n-1 可能是 这就说明了 局部最优 解决不了全局最优

但是从局部最优的情况 逐步地推到全局最优

细节处理 如果当前时开始位置的话不用加上 加油时间

源码

#include<iostream>

#include<cmath>

#include<algorithm>

#include<string>

#include<string.h>

using namespace std;

 

int main()

{

    int L;

    int N, C, T;

    int VR, VT1, VT2;

    double NS[1000];

    double dp[1000];

    while (cin >> L)

    {

        cin >> N >> C >> T;

        cin >> VR >> VT1 >> VT2;

        for (int i = 1; i <= N; i++)

        {

            cin >> NS[i];

        }

        double time;

        int j;

    

        NS[0] = 0;

        NS[N + 1] = L;

        dp[0] = 0;

        for (int i = 1; i <= N+1; i++)

        {

            dp[i] = 1000000;

            for ( j = 0; j < i; j++)

            {

                if ((NS[i] - NS[j]) > C)

                {

                    time = 1.0*C / VT1 + 1.0*(NS[i] - NS[j] - C) / VT2;

                }

                else

                {

                    time = 1.0*(NS[i] - NS[j]) / VT1;

                }

                if (j>0)

                dp[i] = min(dp[i], dp[j] + time + T);

                else

                dp[i] = min(dp[i], dp[j] + time);

            }

            

        }

        double timer = 1.0*L / VR;

        if (timer > dp[N+1])

        {

            cout << "What a pity rabbit!" << endl;

        }

        else

        {

            cout << "Good job,rabbit!"<<endl;

        }

        

    }

}

 

        else

        {

            cout << "Good job,rabbit!"<<endl;

        }

        

    }

}

总结与感想:素数的判断是C语言程序中常考的一个问题,应明白素数的定义,然后和程序结合起来。只输出一个最终结论时,应使用判断,防止多次输出。斐波那契数列等数学知识点很重要,先找出规律再编程会简单很多。写程序更多的还考验的是细心和耐心,读懂题意很重要。(其他感想在每个题后都有具体感想)

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值