暑假集训 7月7日
dfs(尽可能往深搜)栈O(n)
顺序+剪枝
全排列
#include <bits/stdc++.h> using namespace std; typedef long long ll; const int N=10; int path[N]; bool st[N]; int n; void dfs(int u) { if (u==n) { for (int i=0;i<n;i++) { cout<<path[i]<<' '; } cout<<"\n";//关闭同步流以后的注意事项 } for (int i=1;i<=n;i++) { if (!st[i]) { path[u]=i; st[i]=true; dfs(u+1); st[i]=false; } } } signed main() { ios::sync_with_stdio(0); cin.tie(0); cout.tie(0); cin>>n; dfs(0); return 0; }
acwing 健康的荷斯坦奶牛
#include <bits/stdc++.h> using namespace std; typedef long long ll; const int N=30; bool tog=1; int a[N],val[N]; int v,g; int num[N][N]; vector<int>path,ans; bool check() { memset(val,0,sizeof val); for (int i=0;i<v;i++) { for (int j=0;j<path.size();j++) { val[i]+=num[path[j]][i]; } if (val[i]<a[i])return false; } if (ans.empty()||ans.size()>path.size()||(ans.size()==path.size()&&ans>path)) return true; return false; } void dfs(int u) { if (u>g) { if (check())ans=path; return; } //不选 path.push_back(u); dfs(u+1); path.pop_back(); //选 dfs(u+1); } signed main() { cin>>v; for (int i=0; i<v; i++)cin>>a[i]; cin>>g; for (int i=0; i<g; i++) { for (int j=0; j<v; j++) { cin>>num[i][j]; } } dfs(0); int w=ans.size(); cout<<w<<' '; for (int i=0; i<w; i++) { cout<<ans[i]+1<<' '; } puts(""); return 0; }
acwing 小猫爬山
#include <bits/stdc++.h> using namespace std; typedef long long ll; const int N=30; int n,w,ans=18; int a[N],vol[N]; void dfs(int u,int num) { if (num>=ans)return; if (u==n) { ans=num; return; } for (int i=0;i<num;i++) { if (vol[i]+a[u]<=w) { vol[i]+=a[u]; dfs(u+1,num); vol[i]-=a[u]; } } vol[num]=a[u];//再开一个车筐 dfs(u+1,num+1); vol[num]=0; } signed main() { cin>>n>>w; for (int i=0;i<n;i++) { cin>>a[i]; } sort(a,a+n); reverse(a,a+n);//从大到小排序 dfs(0,0); cout<<ans<<"\n"; return 0; }
1<<9-1=111111111
1<<9=1000000000
再减1就是111111111(二进制)
acwing 数独(人没了)
#include <bits/stdc++.h> using namespace std; typedef long long ll; const int N=9,M=1<<N; int ones[M],MAP[M]; int row[N],col[N],cell[3][3]; char str[100]; void init() { for (int i=0; i<N; i++) row[i]=col[i]=(i<<N)-1; for (int i=0; i<3; i++) for (int j=0; j<3; j++) cell[i][j]=(1<<N)-1; } void draw(int x,int y,int t,bool is_set) { if (is_set)str[x*N+y]='1'+t; else str[x*N+y]='.'; int v=1<<t; if (!is_set)v=-v; row[x]-=v; col[y]-=v; cell[x/3][y/3]-=v; } int lowbit(int x) { return x&-x; } int get(int x,int y) { return row[x]&col[y]&cell[x/3][y/3]; } bool dfs(int cnt) { if (!cnt)return true; int mi=10; int x,y; for (int i=0; i<N; i++) for (int j=0; j<N; j++) if (str[i*N+j]=='.') { int st=get(i,j); if (ones[st]<mi) { mi=ones[st]; x=i,y=j; } } int st=get(x,y); for (int i=st;i;i-=lowbit(i)) { int t=MAP[lowbit(i)]; draw(x,y,t,true); if (dfs(cnt-1))return true; draw(x,y,t,false); } return false; } signed main() { for (int i=0; i<N; i++)MAP[1<<i]=i; for (int i=0; i<1<<N; i++) for (int j=0; j<N; j++) ones[i]+=i>>j&1; while (cin>>str,str[0]!='e') { init(); int cnt=0; for (int i=0,k=0; i<N; i++) for (int j=0; j<N; j++,k++) if (str[k]!='.') { int t=str[k]-'1'; draw(i,j,t,true); } else cnt++; dfs(cnt); puts(str); } return 0; }
bfs(一层一层搜)队列 O(2^n)最短性
dijkstra
floyd
二分图
补题:
B - Latin Squares
凭什么呀,没说多组输入好吗。。。
#include <bits/stdc++.h> using namespace std; typedef long long ll; const int N=120; string s[N]; int cnt[N][N]; int num[N][N]; signed main() { int n,i,j,k; while (cin>>n) { memset(cnt,0,sizeof cnt); memset(num,0,sizeof num); bool f=1,ff=1; for (i=0; i<n; i++) { cin>>s[i]; } for (i=0; i<n; i++) { for (j=0; j<n; j++) { if (s[i][j]>='A'&&s[i][j]<='Z') s[i][j]=s[i][j]-'A'+10; else if (s[i][j]>='0'&&s[i][j]<='9') s[i][j]-='0'; } } for (i=1; i<n; i++) { if (s[i][0]==s[0][i]&&(int)(s[0][i]-s[0][i-1])==1) { continue; } else { ff=0; break; } } for (i=0; i<n; i++) { for (j=0; j<n; j++) { cnt[i][(int)s[i][j]]++; } for (k=0; k<=35; k++) if (cnt[i][k]>1)f=0; } for (j=0; j<n; j++) { for (i=0; i<n; i++) { num[j][(int)s[i][j]]++; } for (k=0; k<=35; k++) if (num[j][k]>1)f=0; } if (!f)puts("No"); else if (f&&!ff)puts("Not Reduced"); else if (f&&ff)puts("Reduced"); } return 0; }
K - Star Arrangements
简单水题,当时没看懂题意。。。
#include <bits/stdc++.h> using namespace std; typedef long long ll; int main() { int n; cin>>n; printf("%d:\n",n); int x=n/2; if (n%2)x+=1; int i,j; for (i=2;i<=x;i++) { for (j=i-1;j<=i;j++) { int a=i,b=j; if ((b==a-1)&&((n%(a+b)==a)||(n%(a+b)==0))) printf("%d,%d\n",a,b); else if (b==a) { if (n%a==0)printf("%d,%d\n",a,a); } } } return 0; }
H - Unloaded Die
问的是改的概率差值最小是多少,所以用期望的差值除以最大的概率就行。(雀食)
#include <bits/stdc++.h> using namespace std; typedef long long ll; const int N=10; double a[N]; int main() { double ans=0; double ma=-0x3f3f3f3f; for (int i=1; i<=6; i++) { cin>>a[i]; ma=max(ma,a[i]); ans+=i*a[i]; } double res=abs(3.5-ans); printf("%.3lf\n",res/ma*1.0); return 0; }
题意:给a,b两个数,求a到b所有数的因数和。
题目分析:我们考虑依次枚举1-n中的每一个约数,比如在1-7中,2是2、4、6的约数,3是3、6的约数,4是4的约数,可以发现每一个约数x在1-7中出现的次数是7/x(向下取整),推广到一般情况,对于1-n中的约数x,它最多是n/x个 数 的因子,也就是说,我们要求S(题目描述中有),可以分别求出每一个约数(这里的约数就是1-n中的每一个数)出现的次数并和约数相乘在累加。
比如:
1-n: 1 2 3 4 5 6 7 8 9 10
次数: 10 5 3 2 2 1 1 1 1 1
如果暴力找的话,时间复杂度太高,所以就用到了除法分块,经过观察可以发现,有某个区间的约数,出现的次数是一样的,所以用除法分块将这个区间找到,然后根据数列性质求和。
所谓分块,就是把一段数分成不同的区间,而这些区间的每一个数除以同一个数的值是相同的,所以我们就把这些区间统一处理,就不用再来一个一个遍历
例: 问题中我们假设n = 10。那么我们现在分一下{1},{2},{3},{4,5},{6,7,8,9,10}。
我们知道初始l肯定是等于1,每次算到了r后,再把l更新到r + 1即可。那么关键是r怎么确定?
先一步一步解释: (n / l)代表的是值为(n / l)的一类数的评定标准,也是这个区间的每一个数对答案的增长的价值。
那么n / (n/l),就是代表这一类数的最大值(也就是右端点r)。
以下式子都可以用除法分块
(除法分块)不会
#include <bits/stdc++.h> using namespace std; typedef long long ll; #define ull unsigned long long ull l,r; ull num(ull n) { ull sum=0; for(ull l=1,r;l<=n;l=r+1) { r=n/(n/l);//除法分块 sum=sum+(n/l)*(r-l+1)*(l+r)/2;//等差数列求和 } //(n/l)为该因子出现的次数,n/(n/l)为出现该因子次数的最大因子 return sum; } void solve() { ull a,b; cin>>a>>b; cout<<num(b)-num(--a)<<"\n"; } signed main() { int t=1; //cin>>t; while (t--) { solve(); } return 0; }
范围
F - Purple Rain(最大子段和)
#include <bits/stdc++.h> using namespace std; typedef long long ll; const int N=1e5+10; int q[N]; signed main() { string s; cin>>s; int len=s.size(); if (len==1)puts("1 1"); s="#"+s; for (int i=1;i<=len;i++){ if (s[i]=='B') q[i]=q[i-1]+1; else q[i]=q[i-1]-1; } int l=0,r=0; int ma=0,mi=0; for (int i=1;i<=len;i++){ if (ma>q[i]){ ma=q[i]; l=i; } if (mi<q[i]){ mi=q[i]; r=i; } } cout<<min(l,r)+1<<' '<<max(l,r)<<"\n"; return 0; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· AI 智能体引爆开源社区「GitHub 热点速览」
· Manus的开源复刻OpenManus初探
· 写一个简单的SQL生成工具