cccc练习题(选)
L1-009(N个数求和 字符串)
src:https://www.patest.cn/contests/gplt/L1-009
ac代码:
#include<bits/stdc++.h> #define FOR(i,a,b) for(int i=a;i<=b;i++) using namespace std; typedef long long ll; ll a,b,ga,gb; int n; ll num; ll gcd(ll a,ll b){return b%a==0?a:gcd(b%a,a);} void simp(ll&a,ll&b) { if(a==0)return; ll tmp=gcd(abs(a),abs(b)); a/=tmp;b/=tmp; } int main() { cin>>n; char ch; cin>>a>>ch>>b; ga=a;gb=b;simp(ga,gb); for(int i=1;i<n;i++){ cin>>a>>ch>>b; if(a==0)continue; simp(a,b); ga=(ga*b+a*gb); gb*=b; simp(ga,gb); } if(ga==0)cout<<0<<endl; else {if(ga<0){cout<<'-';ga=abs(ga);} if(ga>=gb){ num=ga/gb; ga%=gb; } if(num)cout<<num; if(ga){ if(num)cout<<' '; cout<<ga<<'/'<<gb; } cout<<endl; } return 0; }
L2-018
src:https://www.patest.cn/contests/gplt/L2-018
多项式除法的思路是,先用a多项式的最高次数项除b多项式的最高次数项,得到一项多项式(大概就是先试出一项把a的最高项消掉酱紫~~~),然后用a多项式减去这一项乘b(试出一项后减掉嘛~~~)
ac代码:
#include<bits/stdc++.h> #include<string> #define FOR(i,a,b) for(int i=a;i<=b;i++) using namespace std; int n; #define eps 0.05 struct { int e;double c; }p[10000+50],ans[10000];//ans 商或余 int main() { ios::sync_with_stdio(false); map<int,double>q;//用map来改比较方便 int n,m,tail=0;//因为指数是固定的,系数是用来修改的,所以指数当作下标!!! cin>>n; //m 被除数多项式指数的最高次 int e; double c; for(int i=1;i<=n;i++){ cin>>e>>c; if(i==1)m=e; q[e]=c; } cin>>n; for(int i=1;i<=n;i++){ cin>>p[i].e>>p[i].c; } while(m>=p[1].e){ double change=q[m]/p[1].c; int edif=m-p[1].e; if(fabs(change)>=eps){//四舍五入,所以大于0.05的照单全收~~~ ans[tail].c=change;ans[tail++].e=edif; for(int i=1;i<=n;i++){ q[p[i].e+edif]-=p[i].c*change; } } else m--; while(m>=p[0].e&&fabs(q[m])<0.05)m--; } cout<<tail; if(tail==0)cout<<" 0 0.0"; FOR(i,0,tail-1)cout<<' '<<ans[i].e<<' '<<fixed<<setprecision(1)<<ans[i].c; cout<<endl; tail=0; while(m>=0){ if(fabs(q[m])>=eps){ ans[tail].e=m; ans[tail++].c=q[m]; } m--; } cout<<tail; if(!tail)cout<<" 0 0.0"; FOR(i,0,tail-1)cout<<' '<<ans[i].e<<' '<<fixed<<setprecision(1)<<ans[i].c; cout<<endl; return 0; }
L2-001紧急救援(最短路径改)!
src:https://www.patest.cn/contests/gplt/L2-001
这题就是求从s到d的最短路径有几条勒,然后在这些最短路径中找出能带的最多人数的那条路,记录能带的最多人数,然后记录一下路径!!!
酱紫蛤,,,用lu[]记录s到节点u的路数,gp[]记录s到节点u的最大人数,pre[]记录路径~~~
基本逻辑就是:如果dis[u]+e[u][v]<dis[v]或==时,更新lu[v],gp[v] dis[]是第一判断条件,通过判断dis[]来判断是否更新其他值~~~本质上就是dij带上其他要维护的值酱紫~~~
ac代码:
#include<bits/stdc++.h> #include<string> #define FOR(i,a,b) for(int i=a;i<=b;i++) using namespace std; #define siz 505 #define inf 99999999 int n,m,s,d; int num[siz],lu[siz],dis[siz],Enum=0,pre[siz],gp[siz]; bool vis[siz]; struct { int to,ne,len; }edge[siz*siz]; int head[siz]; void add_edge(int a,int b,int c) { edge[Enum].to=b; edge[Enum].len=c; edge[Enum].ne=head[a]; head[a]=Enum++; } void init() { memset(head,-1,sizeof(head)); FOR(i,0,n){dis[i]=inf;lu[i]=0;} lu[s]=1;dis[s]=0; memset(pre,-1,sizeof(pre)); memset(vis,false,sizeof(vis)); } void dij()//最短路径条数,最多人数,记录路径 { for(int i=1;i<=n;i++){ int minn=inf,k=0; FOR(j,0,n-1)if(!vis[j]&&dis[j]<minn){ minn=dis[j];k=j; } if(minn==inf)break; vis[k]=true; for(int j=head[k];j!=-1;j=edge[j].ne){ int v=edge[j].to; if(dis[v]==dis[k]+edge[j].len){ lu[v]+=lu[k]; if(gp[k]+num[v]>gp[v]){ gp[v]=gp[k]+num[v]; pre[v]=k; } } else if(dis[v]>dis[k]+edge[j].len){ dis[v]=dis[k]+edge[j].len; pre[v]=k; lu[v]=lu[k];gp[v]=num[v]+gp[k]; } } } } void print(int k) { if(k==-1)return; print(pre[k]); if(k==s)cout<<k; else cout<<' '<<k; } int main() { ios::sync_with_stdio(false); cin>>n>>m>>s>>d; int a,b,c; FOR(i,0,n-1){cin>>num[i];gp[i]=num[i];} init(); for(int i=1;i<=m;i++){ cin>>a>>b>>c; add_edge(a,b,c); add_edge(b,a,c); } dij(); cout<<lu[d]<<' '<<gp[d]<<endl; print(d); return 0; }
L2-020. 功夫传人
用dfs直接传值方便,如果用bfs记得某个人的功力传完一次后清零,免得多个上级传下来造成多重累加的问题
src:https://www.patest.cn/contests/gplt/L2-020
ac代码:
#include<bits/stdc++.h> #include<string> #define FOR(i,a,b) for(int i=a;i<=b;i++) using namespace std; #define siz 100000+10 #define inf 99999999 int n; double z, r, ans = 0.0; vector<int>head[siz]; bool ck[siz]; void read() { int j, k; for (int i = 0; i<n; i++) { cin >> j; if (j == 0) { cin >> k; head[i].push_back(k); ck[i] = true; } else { while (j--) { cin >> k; head[i].push_back(k); } } } } void dfs(int id, double pas)//功力直接传,不用存着~~~这样就避免了多个上级传下的功力累加的问题!!! { if (ck[id]) { ans += pas*head[id][0]; } else { for (vector<int>::iterator it = head[id].begin(); it != head[id].end(); it++) { int v = *it; dfs(v, pas*r); } } } int main() { ios::sync_with_stdio(false); cin >> n >> z >> r; r /= 100; r = 1 - r; ans = 0; memset(ck, false, sizeof(ck)); read(); /*for (vector<int>::iterator it = head[0].begin(); it != head[0].end(); it++) { int v = *it; dfs(v, z*r); }*/ dfs(0, z); cout << (int)ans << endl; return 0; }
#include<bits/stdc++.h>//bfs #include<string> #define FOR(i,a,b) for(int i=a;i<=b;i++) using namespace std; #define siz 100000+10 #define inf 99999999 int n; double z,r,val[siz]; vector<int> head[siz]; vector<int> mag; double mg[siz]; void read() { int j,k; for(int i=0;i<n;i++){ cin>>j; if(j==0){ mag.push_back(i); cin>>k;mg[i]=k; } else while(j--){ cin>>k; head[i].push_back(k); } } } void solve() { queue<int>q; q.push(0); while(!q.empty()){ int u=q.front();q.pop(); for(vector<int>::iterator it=head[u].begin();it!=head[u].end();it++){ int v=*it; val[v]+=val[u]*r; q.push(v); } if(mg[u]==0.0)val[u]=0; } double ans=0; for(int i=0;i<mag.size();i++){ int u=mag[i]; ans+=val[u]*mg[u]; } cout<<(int)ans<<endl; } int main() { ios::sync_with_stdio(false); cin>>n>>z>>r; r/=100; r=1-r; memset(val,0,sizeof(val)); val[0]=z; read(); solve(); return 0; }
L2-007 家庭房产(没过QAQ)
src:https://www.patest.cn/contests/gplt/L2-007
代码:
#define _CRT_SECURE_NO_WARNINGS #include<bits/stdc++.h> #include<string> #define FOR(i,a,b) for(int i=a;i<=b;i++) using namespace std; int n; struct { int id, pa, ma,num,area; }peo[1005];//可能有房产的就是这up to1000人,所以这peo[]记录有效的信息!!! struct node { int id, sum; double pnum, parea; bool flag=false; }ans[10000 + 10];//考虑到其他没房产的但是编号会更小,就开10000 int fa[10000];//通过fa[]记录集合,ans[]记录各集合具体信息,也可以把fa[]放到ans[]里 bool vis[10000]; void init() { FOR(i, 1, 10000)fa[i] = i; memset(vis, false, sizeof(vis)); } int find(int u) { if (fa[u] == u)return u; else return fa[u] = find(fa[u]); } void Union(int u, int v) { int fu = find(u), fv = find(v); if (fu < fv)fa[fv] = fu; else fa[fu] = fv; } bool cmp(node a, node b) { if (a.parea != b.parea)return a.parea > b.parea; else return a.id < b.id; } int main() { ios::sync_with_stdio(false); init(); cin >> n;//如果编号很长的话,写个hash函数映射到数组上 FOR(i, 1, n) {//一边是n数组记录有房产的人的信息,另一边是10000编号构成的集合 cin >> peo[i].id >> peo[i].pa >> peo[i].ma; vis[peo[i].id] = true; if (peo[i].pa != -1) { vis[peo[i].pa] = true; Union(peo[i].id, peo[i].pa); } if (peo[i].ma != -1) { vis[peo[i].ma] = true; Union(peo[i].id, peo[i].ma); } int k, kid; cin >> k; while(k--) { cin >> kid; vis[kid] = true; Union(peo[i].id, kid); } cin >> peo[i].num >> peo[i].area; } FOR(i, 1, n) {//把n数组中的值加到集合里 int id = find(peo[i].id); ans[id].id = id; ans[id].pnum+=peo[i].num; ans[id].parea += peo[i].area; ans[id].flag = true;//集合中编号最小的标记 } int cnt = 0; FOR(i, 1, 10000) {//ans就是把各个集合中最小的取出来 if (vis[i]) { ans[find(i)].sum++; } if (ans[i].flag) { cnt++; } } FOR(i, 1, 10000) { if (ans[i].flag) { ans[i].pnum = ans[i].pnum*1.0 / (double)ans[i].sum*1.0; ans[i].parea = ans[i].parea*1.0/(double)ans[i].sum*1.0; } } sort(ans + 1, ans + 10001, cmp); cout << cnt << endl; FOR(i, 1, cnt) { cout << setfill('0') << setw(4) << ans[i].id; cout << ' ' << ans[i].sum << ' ' << fixed << setprecision(3) << ans[i].pnum << ' ' << setprecision(3) << ans[i].parea << endl; } return 0; }
L3-003 社交集群(并查集)
src:https://www.patest.cn/contests/gplt/L3-003
ac代码:
#define _CRT_SECURE_NO_WARNINGS #include<bits/stdc++.h> #include<string> #define FOR(i,a,b) for(int i=a;i<=b;i++) #define RFOR(i,a,b) for(int i=a;i>=b;i--) using namespace std; int root[1001];//喜欢某个活动的群体在的集合的根节点; int fa[1002]; int n; void init() { memset(root, -1, sizeof(root)); } int find(int u) { return fa[u] == 0?u:find(fa[u]); } void Union(int u, int v) { int fu = find(u), fv = find(v); if (fu != fv)fa[fu] = fv; } int main() { ios::sync_with_stdio(false); init(); cin >> n; int k,m; char ch; FOR(i, 1, n) { cin >> k>>ch; FOR(j, 1, k) { cin >> m; int rt = root[m]; if (rt == -1) { root[m] = i; continue; } else { int f = find(i); fa[f] = find(rt); } } } int ans[1001] = { 0 }, cnt = 0; FOR(i, 1, n) { if (fa[i] == 0) { cnt++; ans[i]++; } else { ans[find(i)]++; } } sort(ans + 1, ans + n + 1); cout << cnt << endl; cout << ans[n]; for (int i = n-1; i >n-cnt; i--) { cout << " " << ans[i]; } cout << endl; return 0; }
1074. 宇宙无敌加法器(水题)
src:https://www.patest.cn/contests/pat-b-practise/1074
注意最后一个样例结果是0
ac代码:
#include<bits/stdc++.h> #include<string> #define FOR(i,a,b) for(int i=a;i<=b;i++) using namespace std; #define siz 505 #define inf 99999999 int jin[30],a[30],b[30],ans[30]; string s; int mm; void change(int* t) { t[0]=(int)s.size(); int pos=1; for(int i=t[0]-1;i>=0;i--){ t[pos++]=s[i]-'0'; } } void solve() { int flag=0; memset(ans,0,sizeof(ans)); for(int i=1;i<=mm;i++){ ans[i]=flag+a[i]+b[i];flag=0; while(ans[i]>=jin[i]){ flag=ans[i]/jin[i]; ans[i]%=jin[i]; } } if(flag)ans[++mm]=1; while(ans[mm]==0&&mm>1)mm--; for(int i=mm;i>=1;i--)cout<<ans[i];cout<<endl; } int main() { ios::sync_with_stdio(false); cin>>s; change(jin); FOR(i,1,jin[0])if(jin[i]==0)jin[i]=10; cin>>s; change(a); cin>>s; change(b); mm=max(a[0],b[0]); FOR(i,a[0]+1,mm)a[i]=0;FOR(i,b[0]+1,mm)b[i]=0; solve(); return 0; }

浙公网安备 33010602011771号