if(答案 && 测试点TLE)
问题,洛谷P1036 选数
已知n个给出的整数 ,以及 1 个整数 k(k<n)。从 n 个整数中任选 k 个整数相加,可分别得到一系列的和。例如当 n=4,k=3,4 个整数分别为 3,7,12,19 时,可得全部的组合与它们的和为:
3+7+12=22
3+7+19=29
7+12+19=38
3+12+19=34
现在,要求你计算出和为素数共有多少种。
例如上例,只有一种的和为素数:3+7+19=29。
my原答案
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
| #include<iostream> #include<vector> using namespace std;
typedef long long ll;
int su(ll n){ if(n<=1) return 0; if(n==2) return 1; if(n%2==0) return 0; for(ll i=3;i*i<=n;i+=2){ if(n%i==0){ return 0; } } return 1; }
void dfs(int start,int count,ll sum,int k,int n,vector<ll>& nums,int& prime_count){ if(count==k){ if(su(sum)){ prime_count++; } return; } for(int i=start;i<n;i++){ dfs(i+1,count+1,sum+nums[i],k,n,nums,prime_count); } }
int main(){ ios::sync_with_stdio(false); cin.tie(0);
int n,k; cin>>n>>k; vector<ll> nums(n); for(int i=0;i<n;i++){ cin>>nums[i]; } int prime_count=0; dfs(0,0,0,k,n,nums,prime_count); cout<<prime_count<<endl; 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
| #include<iostream> #include<vector> using namespace std;
typedef long long ll;
bool prime(ll n){ if(n<=1) return false; if(n==2) return true; if(n%2==0) return false; for(ll i=3;i*i<=n;i+=2){ if(n%i==0) return false; } return true; }
bool fast_prime(ll n){ if(n<=3) return n>1; if(n%2==0 || n%3==0) return false;
for(ll i=5;i*i<=n;i+=6){ if(n%i==0 || n%(i+2)==0) return false; } return true; }
void dfs(int start,int cnt,ll sum,int k,int n,vector<ll>& nums,int& prime_cnt){ if(count==k){ if(fast_prime(sum)){ prime_cnt++; } return; }
if(n-start<k-cnt) return;
for(int i=start;i<n;i++){ dfs(i+1,cnt+1,sum+nums[i],k,n,nums,prime_cnt); } }
|
好的果然过了。
总结
- 算法复杂度分析的重要性:最初只考虑了 n=20 较小,但没考虑数字范围可能很大(5×10⁶)。不仅要看输入数量,还要看数值范围
- 剪枝思想的威力
1
| if (n - start < k - count) return;
|
在搜索算法中,尽早排除无效路径
- 素数判断优化技巧(纯菜
龟速前进中