JYU程序设计决赛题解与思考(更新中)

被绿的小华

题目大意就是给出一个01串表示的二进制数是否为3的倍数。

方法1:暴力

直接用快速幂暴力求解,求解的过程中同时模3。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<string>
 4 #include<cstring>
 5 #include<algorithm>
 6 #include<cmath>
 7 #define MAXN 10000
 8 #define int long long
 9 #define mod 3
10 using namespace std;
11 int n,m,ans=0;
12 int a[MAXN];
13 inline int pow_(int x,int n){
14     int cnt=1;
15     while(n){
16         if(n&1)
17             cnt=cnt*x%mod;
18         x=x*x%mod;
19         n>>=1;
20     }
21     return cnt%mod;
22 }
23 signed main()
24 {
25     string s;
26     cin>>s;
27     for(int i=s.size()-1,j=0;i>=0;i--,j++){
28         if(s[i]=='1'){
29             ans=ans+pow_(2,j);
30             ans%=mod;
31         }
32     }
33     if(ans==0) cout<<"Y"<<endl;
34     else cout<<"N"<<endl; 
35     return 0;
36 }
暴力

方法2:数学

二进制数的奇数位1的个数与偶数位1的个数的差能被3整除,则这个数是3的倍数。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<list>
 4 #include<string>
 5 #include<map>
 6 #include<set>
 7 #include<queue>
 8 #include<stack>
 9 #include<cmath>
10 #include<ctime> 
11 #include<algorithm>
12 #include<cstring>
13 #define  sc scanf
14 #define  pr printf
15 #define MAXN 10001
16 #define INF 9999999999
17 #define endd puts("");
18 #define int long long
19 #define il inline
20 #define PI  3.1415926535898
21 #define INF_MIN -214783647
22 using namespace std;
23 il int read() {
24     int s = 0, f = 1;
25     char ch = getchar();
26     while (ch<'0'||ch>'9') {  if (ch == '-')  f = -1;  ch = getchar();  }
27     while (ch>='0'&&ch<='9') {  s = s * 10 + ch - '0';  ch = getchar();  }
28     return s * f;
29 }
30 /******************************head*****************************************/
31 int pow_(int a,int n){
32     int cnt=1;
33     while(n){
34         if(n&1)
35             cnt=cnt*a;
36         a=a*a;
37         n>>=1;
38     }
39     return cnt;
40 }
41 signed main()
42 {
43     int num1=0,num2=0; 
44     string s;
45     cin>>s;
46     for(int i=s.size()-1;i>=0;i--){
47         if(s[i]=='1'){
48             if(i&1) num1++;
49             else num2++; 
50         }
51     }
52     if(abs(num1-num2)%3==0) cout<<"Y";
53     else cout<<"N";
54     return 0;
55 }
数学

 

证明:

对于二进制数的偶数位:

2^0%3=1;

2^2=2^0*4;

2^2%3=(2^0%3)*(4%3)=(2^0%3)*1=2^0%3=1;

则2^2%3==2^0%3;

2^4%3=(2^2%3)*(4%3)=(2^2%3)*1=2^2%3=2^0%3=1;

则2^4%3==2^2%3==2^0%3;

以此类推

(2^2n)%3=2^(2(n-1))%3*(4%3)=2^(2(n-1))%3*1=2^(2(n-2))%3*(4%3)……=2^(2(n-n))%3*4%3=2^0*(4%3)=2^0*1=1*1;

得(2^2n)%3=2^0*1=1;

而二进制数的奇数位同理可证得(2^(2n+1))%3=2^1%3=2;

从而得出一个二进制数的奇数位%3为2,二进制数的偶数位%3为1;

 

奇数位1的个数与偶数位1的个数的差有两种情况:

(1)奇数位1的个数与偶数位1的个数相等;

若一个二进制数有n个奇数位的1,m个偶数位的1,且n=m,由上面证得的结论可知二进制数的奇数位%3为2,偶数位%3为1;

则这个二进制数%3的值为n(1+2)%3=3n%3=0,这个二进制数能被3整除;

(2)奇数位1的个数与偶数位1的个数不等;

若一个二进制数有n个奇数位的1,m个偶数位的1,且n>m,由上面证得的结论可知二进制数的奇数位%3为2,偶数位%3为1;

则这个二进制数%3的值为m(1+2)%3+(n-m)*2%3,若n-m%3==0,则(n-m)*2%3==0,可得结论若奇数位的1大于偶数位的1的个数且个数差为3的倍数,则该二进制数是3的倍数;

若一个二进制数有n个奇数位的1,m个偶数位的1,且n<m,由上面证得的结论可知二进制数的奇数位%3为2,偶数位%3为1;

则这个二进制数%3的值为n(1+2)%3+(n-m)*1%3,若n-m%3==0,则(n-m)*1%3==0,可得结论若奇数位的1小于偶数位的1的个数且个数差为3的倍数,则该二进制数是3的倍数;

综上所述可证得:二进制数的奇数位1的个数与偶数位1的个数的差能被3整除,则这个数是3的倍数。

 

posted @ 2020-12-14 15:22  面向题目编程  阅读(221)  评论(0)    收藏  举报