数学问题小结

    这几天,学习并完成了数学类的一些知识和题目,包括素数,期望,gcd等等。。。。。。进行一个简单的总结。

 

首先是素数。当题目中的数据量比较小时,我们可以用最简单的方法去一一搜素判断该数是否是一个素数。判断的方法则是让它与比他小的数一一作除法,若能够被整除,则是合数,否则是质数。为了降低时间复杂度,我们可以只判断2到这个数的平方根之间的数,因为能够被这个数整除的数一定小于等于这个数的平方根。代码如下:

 1 int isprime(long long n)
 2 {
 3     long long i;
 4     if (n==2)
 5     {
 6         return 1;
 7     }
 8     for (i=2;i<=sqrt(n);i++)
 9     {
10         if (n%i==0)
11         {
12             return 0;
13         }
14     }
15     return 1;
16 }

  用这种方法,虽然可以准确的找出素数,但如果题目中的数据量很大,我们就要考虑另外一种方法了,提前将所有的素数存放在一个地方,当我们判断的时候,只需要判断我们是否存放这个数即可。这样,我们就不用每次都进行判断,而是只需判断查找一次,大大节省了时间。那么,我们怎样寻找所有的素数呢,我们可以先假定所有的数都是质数,然后从2开始,将2的所有倍数都标记为合数,之后是3,以此类推。。。。。。。为了避免重复标记,节约时间,我们通常采用如下的快速筛素数的方法:若当前标记的是i的倍数,如果i是前面已经标记了的数的倍数,便不再进行标记。代码如下:

 1 #include<stdio.h>
 2 #include<bits/stdc++.h>
 3 using namespace std;
 4 const long long N=10000100; 
 5 int prime[N]={0},num_prime=0;
 6 bool isNotPrime[N]={true,true};
 7 void panprime()
 8 {
 9     long long i,j;
10     for (i=2;i<N;i++)
11     {
12         if(!isNotPrime[i])
13         {
14             prime[num_prime++]=i;
15         }
16         for (j=0;j<num_prime && i*prime[j]<N ;j++)
17         {
18             isNotPrime[i*prime[j]]=true;
19             if (!(i%prime[j]))
20             {
21                 break;
22             }
23 
24         }
25     }
26 }

当然,如果数据比较小,还是用第一种方法吧。说不定,用第一种方法所需的时间还比第二种小哦,因为找出所有的素数也是需要时间的。。。

结论:数据量比较小的时候选方法一,数据量比较大(需判断成千上万个数)时选方法二!

 

之后是GCD,用辗转相除法寻找两个数的最大公因数。是更好的选择,比传统的逐步寻找法快得多。

 

1 int gcd(int a,int b)
2 {
3     if (b==0)
4     {
5         return a;
6     }
7     gcd(b,a%b);
8 }

 

 

 

最后,上一道题吧:http://www.fjutacm.com/Problem.jsp?pid=2519

  其实,这个题就是一个典型的找最大公因数的题,双方拥有的机会就是最大公因数到最大的数之间的个数。解决代码如下:

 1 #include<stdio.h>
 2 #include<bits/stdc++.h>
 3 using namespace std;
 4 long gcd(long a,long b)
 5 {
 6     if (b==0)
 7     {
 8         return a;
 9     }
10     gcd(b,a%b);
11 }
12 int main()
13 {
14     long a[105];
15     long n,i,j;
16     long maxA=0;
17     scanf("%ld",&n);
18     for (i=0;i<n;i++)
19     {
20         scanf("%ld",&a[i]);
21         maxA=max(maxA,a[i]);
22     }

24 
25     long min=gcd(a[0],a[1]);
26     
27     for(i=0;i<n;i++)
28       for (j=i+1;j<n;j++)
29       {
30           long ans;
31           
32          ans=gcd(a[i],a[j]);
33          if (min>ans)
34          {
35              min=ans;
36          }
37       }
38 
39     

44       long key;
45       key=maxA/min;
46       key=key-n;

48       if (key%2==0)
49       {
50           printf("Bob\n");
51       }
52       else
53       {
54           printf("Alice\n");
55       }
56     
57     return 0;
58  } 

 

再来看看这个题:https://atcoder.jp/contests/abc182/tasks/abc182_c?lang=en

这个题的意思就是要寻找一个数,删除其中的几个数字后,得到的数是三的倍数。因为三的倍数的判定方法就是看这个数字的和是否是三的倍数。一个数字的和就只有3种情况:刚好是3的倍数,3的倍数余1,3的倍数余2.第一种情况不用处理,输出0就行。第二种情况要小心,它有两种情况,我就是少考虑了一种,而WA了几发:第一种是可以删除一个余数为1的数,第二种是删除2个余数为2的数,因为,两个余数为2的数的和余数的和为4,4对3取余正好是1。第三种情况则是删除一个余数为2的数字或者删除两个余数为1的数字。优先考虑前面的一种方案。至于统计余数为一和余数为二的数字,我们可以利用字符串来处理每一个数字,这样,既避免了数字非常大存不下情况的发生,又可以使数字的处理更加方便快捷,代码如下:

 1 #include<stdio.h>
 2 #include<string.h>
 3 int main()
 4 {
 5     char n[20];
 6     gets(n);
 7   
 8     int nn=strlen(n);
 9     int s=0;
10     int ss[4]={0},i;
11     for (i=0;i<strlen(n);i++)
12     {
13         s=s+n[i]-48;
14 
15         if ((n[i]-48)%3==1)
16         {
17             ss[1]++;
18         }
19         if ((n[i]-48)%3==2)
20         {
21             ss[2]++;
22         }
23     }
24 
25     if (s%3==0)
26     {
27         printf("0");
28         return 0;
29     }
30     else
31     {
32         s=s%3;
33         if (s==1)
34         {
35             
36             if (ss[1]>=1 && (nn-1)>0)
37             {
38                 printf("1");
39                 return 0;
40             }
41             else if (ss[2]>=2 && (nn-2)>0)
42             {
43                 printf("2");
44                 return 0;
45              } 
46             else
47             {
48                 printf("-1");
49             }
50         }
51         if (s==2)
52         {
53             if (ss[2]>=1 && (nn-1)>0)
54             {
55                 printf("1");
56                 return 0;
57             }
58             else if (ss[1]>=2 && (nn-2)>0)
59             {
60                 printf("2");
61                 
62             }
63             else
64             {
65                 printf("-1");
66             }
67         }
68     }
69     return 0;
70     
71 }

 

posted @ 2021-01-22 13:26  D5181  阅读(127)  评论(0编辑  收藏  举报