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;
}
View Code

 

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;
}
View Code

 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;
}
View Code

 

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;
}
View Code
#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;
}
View Code

 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;
}
View Code

 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;
}
View Code

 

 

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;
}
View Code

 

posted @ 2018-03-24 21:03  WindFreedom  阅读(179)  评论(0)    收藏  举报