1 条题解

  • 0
    @ 2026-4-7 10:33:45
    本题是组合回溯(dfs)的入门题
    区分组合回溯和排列回溯的使用
    #include<bits/stdc++.h>
    using namespace std;
    #define int long long
    /* 开始学习组合枚举+回溯---本质就是暴力DFS 
       1:明确你的dfs的含义(利用上下层实现本层)《----为了实现这个含义你要啥参数随便
       2:起点与终点
       3:三大注意:可选?重复?越界? 
      ================================================
      okok 回到本题:n个数 选k个+ sum==质数的个数 
      ===================================
      okok 学到dfs的精髓了:我们之前的随意暴力选举本质是排列(n!)
                            但是本题仅是组合--(cn,m)
    		如果使用排列一定一定会爆
      讲讲如何进行组合排序:多一个start 让每次下层枚举都有个开头(不重复枚举)						 
    */
    const int N=25;
    int a[N];
    bool f[N];
    int n,k;
    int ans;
    bool is_prime(int x)//是返回1 
    {
      if(x<2) return 0;	
      for(int i=2;i<=x/i;i++)
       if(x%i==0) return 0;
      return 1; 
    }
    //组合枚举 
    void dfs(int t,int sum,int start)
    {
    	//终点
    	if(t==k)
    	{
    	  if(is_prime(sum))ans++;
    	  return;	
    	}
    	else
    	for(int i=start;i<n;i++)
    	{
    	  if(!f[i])
    	  {
    	    f[i]=1;
    		dfs(t+1,sum+a[i],i+1);
    		f[i]=0;	
    	  }	
    	} 
    }
    
    //排列枚举 
    //void dfs(int t,int sum)//当前选了几个数,当前的sum 
    //{
    //  //终点
    //  if(t==k)
    //  {
    //    if(is_prime(sum)) ans++;
    //	return; 	
    //  }	
    //  //遍历
    //  else
    //  for(int i=0;i<n;i++)
    //  {
    //  	if(!f[i])//没选过 
    //	  {
    //	  	f[i]=1;
    //		dfs(t+1,sum+a[i]);
    //		f[i]=0;//回溯   
    //	  } 
    //  } 
    //  return;
    //}
    signed main()
    { std::ios::sync_with_stdio(0);
      cin.tie(0),cout.tie(0);
        cin>>n>>k;
    	for(int i=0;i<n;i++) cin>>a[i];
        dfs(0,0,0);
    	cout<<ans<<"\n";		
    	return 0;
    }
    • 1

    信息

    ID
    139
    时间
    1000ms
    内存
    256MiB
    难度
    3
    标签
    递交数
    378
    已通过
    101
    上传者