数论 - 整除问题 --- 整数集合中找出3的最大倍数
#
Mean:
题目描述:给一个包含非负整数的数组(长度为n),找出由这些数字组成的最大的3的倍数,没有的话则输出impossible。
analyse:
首先想到的就是直接暴力,这是最蠢的方法,数据一大的话,必会TLE。
直接用蛮力的话,生成所有的组合,为 2^n个,对每个数字再进行比较判断,需要 O(n)的时间,因为n可能会比较大,需要每个位的比较。
总的时间复杂度为O(n * 2^n).
那么到底要怎么做呢?
首先我们来了解几个数学知识:
1)一个数n对m取余的余数为a1,b为n的每一位数字的和,那么有:n%m=b%m=a1。
例如,如果对于151和它的各位之和7,对于3的余数都为1。
2)一个数是3的倍数,则该数字各位总和为3的倍数。
例如,让我们考虑8760,它是3的倍数,因为数字总和为8 + 7 + 6 + 0 = 21,这是3的倍数。
推论:一个数是3的倍数,那么构成他的数字的排列为一个新的数字,这个数字仍然是3的倍数。
Time complexity:O(nlongn)
Source code:
暴力代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 | // Memory Time // 1347K 0MS // by : Snarl_jsb // 2014-09-10-09.28 #include<algorithm> #include<cstdio> #include<cstring> #include<cstdlib> #include<iostream> #include<vector> #include<queue> #include<stack> #include<map> #include<string> #include<climits> #include<cmath> #define N 100 #define MAXN 100 #define LL long long using namespace std; long long n,summ; long long a[N]; bool cmp(LL a,LL b) { return a>b; } LL ans[N]; LL idx; LL Max; void work( int * b, int n) { LL sum1=0; for ( int i=0;i<n;i++) { sum1+=a[b[i]]; } if (sum1%3==0&&sum1>Max) { Max=sum1; idx=n; for ( int i=0;i<n;i++) { ans[i]=a[b[i]]; } } } void _gen_comb( int * a, int s, int e, int m, int & cnt, int * temp){ int i; if (!m) work(temp,cnt); else for (i=s;i<=e-m+1;i++){ temp[cnt++]=a[i]; _gen_comb(a,i+1,e,m-1,cnt,temp); cnt--; } } void gen_comb( int n, int m) { int a[MAXN],temp[MAXN],cnt=0,i; for (i=0;i<n;i++) a[i]=i+1; _gen_comb(a,0,n-1,m,cnt,temp); } int main() { // freopen("C:\\Users\\ASUS\\Desktop\\cin.cpp","r",stdin); // freopen("C:\\Users\\ASUS\\Desktop\\cout.cpp","w",stdout); while (~ scanf ( "%I64d" ,&n)) { LL sum=0; for ( int i=1;i<=n;++i) { scanf ( "%I64d" ,a+i); sum+=a[i]; } summ=sum; // cout<<sum<<endl; sort(a+1,a+1+n,cmp); if (!(sum%3)) { for ( int i=1;i<=n;i++) { printf ( "%I64d" ,a[i]); } puts ( "" ); continue ; } bool flag=0; for ( int i=n;i>1;--i) { sum-=a[n]; if (!(sum%3)) { for ( int j=1;j<i;j++) printf ( "%I64d" ,a[j]); puts ( "" ); flag=1; break ; } } if (flag) continue ; Max=LONG_LONG_MIN; for ( int i=n;i>=1;--i) { gen_comb(n,i); } if ( sizeof (ans)==0) { puts ( "impossible\n" ); continue ; } sort(ans,ans+idx,cmp); for ( int i=0;i<idx;++i) { printf ( "%I64d" ,ans[i]); } puts ( "" ); } return 0; } |
数学方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 | // Memory Time // 1347K 0MS // by : Snarl_jsb // 2014-09-10-11.37 #include<algorithm> #include<cstdio> #include<cstring> #include<cstdlib> #include<iostream> #include<vector> #include<queue> #include<stack> #include<map> #include<string> #include<climits> #include<cmath> #define N 10000 #define LL long long using namespace std; LL n; LL a[N]; LL ans[N]; LL n1,n2,n3; LL q1[N],q2[N],q3[N]; bool cmp(LL a,LL b) { return a>b; } int main() { // freopen("C:\\Users\\ASUS\\Desktop\\cin.cpp","r",stdin); // freopen("C:\\Users\\ASUS\\Desktop\\cout.cpp","w",stdout); while ( scanf ( "%d" ,&n)!=EOF) { n1=n2=n3=0; LL sum=0; for (LL i=1;i<=n;i++) { scanf ( "%d" ,&a[i]); sum+=a[i]; if (a[i]%3==0) { q1[++n1]=a[i]; } else if (a[i]%3==1) q2[++n2]=a[i]; else q3[++n3]=a[i]; } if (sum%3==0) { sort(a+1,a+1+n); for ( int i=n;i>=1;--i) { printf ( "%d" ,a[i]); } puts ( "" ); continue ; } sort(q1+1,q1+1+n1,cmp); sort(q2+1,q2+1+n2,cmp); sort(q3+1,q3+1+n3,cmp); if (sum%3==1) { if (n2>=1) { n2--; } else if (n3>=2) { n3-=2; } else { puts ( "impossible\n" ); continue ; } } else if (sum%3==2) { if (n1>=2) { n1-=2; } else if (n2>=1) { n2--; } else { puts ( "impossible\n" ); continue ; } } LL idx=0; for ( int i=1;i<=n1;++i) { ans[++idx]=q1[i]; } for ( int i=1;i<=n2;++i) { ans[++idx]=q2[i]; } for ( int i=1;i<=n3;++i) { ans[++idx]=q3[i]; } sort(ans+1,ans+1+idx,cmp); for ( int i=1;i<=idx;i++) { printf ( "%I64d" ,ans[i]); } puts ( "" ); } return 0; } |
作者:北岛知寒
出处:https://www.cnblogs.com/crazyacking/p/3965038.html
版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?