码迷,mamicode.com
首页 > 其他好文 > 详细

2018中国大学生程序设计竞赛 - 网络选拔赛

时间:2019-01-28 23:48:31      阅读:227      评论:0      收藏:0      [点我收藏+]

标签:one   for   font   个数   ras   模型   优先   大学   节点   

传送门

A.HDU6438 Buy and Resell

题意

给你N天N个价格,每天都可以从1.买入一个,2.卖出一个,3.什么都不做,求最高获利

低买高卖问题,这题与其他的差距就是要在满足获利最多的情况下,买卖次数最小;

思路

手算一下发现价格具有传递性;例如数据是1,5,9;
5的时候买入1赚了4;9的时候买入5赚了4;相当于直接把5当成跳板直接9的时候买1;然后再把中间的5当成没有买过的;

建立一个小根堆(优先队列);把当前遇到的天数的价钱放入,然后对于第i天;

1.如果新天数的价钱比堆顶小;说明交易亏本,直接丢入堆中;
2.如果价钱高说明有赚头;
2.1.如果堆顶的是已经跟之前的交易过的,那相当于当前天和之前的那个交易,然后堆顶的变成没有交易的;继续插入;交易次数不变
2.2否则直接交易,交易次数+2

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod=998244353;
const int maxn=1e6+50;
const ll inf=0x3f3f3f3f3f3f;
int a[maxn];
struct node{
    int id;
    int money;
    bool has;
    node(int id,int money,bool has):id(id),money(money),has(has){}
    bool friend operator <(node a,node b){
        if(a.money==b.money)return a.has<b.has;
        return a.money>b.money;
    }
};
int flag[maxn];
int used[maxn];
int main()
{
    std::ios::sync_with_stdio(false);
    std::cin.tie(0);
    std::cout.tie(0);
    int t;
    cin>>t;
    while(t--){
        int n;
        cin>>n;
        ll ans=0;
        ll cnt=0;
        memset(flag,0,sizeof(flag));
        memset(used,-1,sizeof(used));
        for(int i=0;i<n;i++)cin>>a[i];
        priority_queue<node>pq;
        for(int i=0;i<n;i++){
            if(pq.empty())pq.push(node(i,a[i],0));
            else{
                node now=pq.top();
                if(now.money>=a[i])pq.push(node(i,a[i],0));
                else{
                    pq.pop();
                    if(flag[now.id]){
                        ans+=a[i]-now.money;
                        flag[i]=1;flag[now.id]=0;
                        used[i]=used[now.id];
                        used[now.id]=-1;
                        pq.push(node(i,a[i],1));
                        pq.push(node(now.id,a[now.id],0));
                    }
                    else{
                        ans+=a[i]-now.money;
                        cnt+=2;
                        flag[i]=1;flag[now.id]=1;
                        used[i]=now.id;
                        pq.push(node(i,a[i],1));
                    }
                }
            }
        }
        cout<<ans<<" "<<cnt<<endl;
    }
    return 0;
}

C.HDU6440 Dream

题意

对一个质数P,对小于P的非负数定义一种乘法和加法运算,使得其满足封闭性,且对于存在一个数q使得{qk|0< k< p}

思路

费马小定理,比赛随便迷一样的试了一下就A了,自己也不知道怎么解释...

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod=1e9+7;
const int maxn=1e5+50;
const ll inf=0x3f3f3f3f3f3f;
int n;
int vis[maxn];
int size[maxn];
int main()
{
    std::ios::sync_with_stdio(false);
    std::cin.tie(0);
    std::cout.tie(0);
    int t;
    cin>>t;
    while(t--){
        int p;
        cin>>p;
        for(int i=0;i<p;i++){
            cout<<i;
            for(int j=1;j<p;j++){
                cout<<" "<<(i+j)%p;
            }
            cout<<endl;
        }

        for(int i=0;i<p;i++){
            cout<<0;
            for(int j=1;j<p;j++){
                cout<<" "<<(i*j)%p;
            }
            cout<<endl;
        }

    }
    return 0;
}

D.HDU6441 Find Integer

题意

题意:已知a^n+b^n=c^n,给出n和a,求b,c,如果无解输出?1。

思路

费马大定理

  1. a^n+b^n=c^n,n>2时无解。
  2. 当a为奇数时,
    a=2?k+1
    c=k^2+(k+1)^2
    b=c?1
    3.当 a 为偶数
    a=2?k+2
    c=1+(k+1)^2
    b=c?2
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod=998244353;
const int maxn=3e6+50;
const ll inf=0x3f3f3f3f3f3f;

int main()
{
    //std::ios::sync_with_stdio(false);
   // std::cin.tie(0);
    //std::cout.tie(0);
    int t;
    scanf("%d",&t);
    while(t--){
        ll n,a;
        scanf("%lld%lld",&n,&a);
        if(n==0){
            printf("-1 -1\n");
        }
        else if(n==1){
            printf("1 %lld\n",a+1);
        }
        else if(n==2)
            {
                if(a&1){
                    printf("%lld %lld\n",a*a/2,a*a/2+1);
                }
                else{
                    printf("%lld %lld\n",(a/2)*(a/2)-1,(a/2)*(a/2)+1);
                }
            }
        else{
            printf("-1 -1\n");
        }
    }
    return 0;
}

I.HDU6446 Tree and Permutation

题意

题意:给你一颗树,然后让你求n!种序列中,所以得序列和,序列和定义为:A1,A2,A3……AN=A1A2+A2A3+…….An-1An

思路

首先,对于题目给出的n-1条边,我们可以这样考虑,去掉这条边后,将树分成了两部分,一部分有M个节点,另一部分有(N-M)个节点,所以我们必须在这两块中任意选择一个节点才会进过这条边,所以,有N × M× 2 中选择,然后又N!个序列所以对于E这条边,一共又2×N×M×(N-1)!×L的贡献。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod=1e9+7;
const int maxn=1e5+50;
const ll inf=0x3f3f3f3f3f3f;
int n;
int vis[maxn];
int size[maxn];
struct Edge{
    int to;
    int s;
    int t;
    int l;
    Edge(int to,int s,int t,int l):to(to),s(s),t(t),l(l){}
};
ll f[maxn];
int init(){
    f[0]=1;f[1]=1;
    for(int i=2;i<=100000;i++)f[i]=(f[i-1]*i)%mod;
}
ll ans;
vector<Edge>G[maxn];
void dfs(int u){
    vis[u]=1;
    int cnt=1;
    for(int i=0;i<G[u].size();i++){
        Edge &e=G[u][i];
        if(vis[e.to]==0){
            dfs(e.to);
            ll tmp=size[e.to];
            tmp=tmp*(n-tmp)%mod;
            tmp=tmp*2%mod;
            tmp=tmp*e.l%mod;
            tmp=tmp*f[n-1]%mod;
            ans+=tmp;
            ans%=mod;
            cnt+=size[e.to];
        }
    }
    size[u]=cnt;
}

int main()
{
    std::ios::sync_with_stdio(false);
    std::cin.tie(0);
    std::cout.tie(0);
    int t;
    init();
    while(cin>>n){
        for(int i=0;i<=n;i++)G[i].clear();
        for(int i=0;i<=n;i++)size[i]=0,vis[i]=0;
        ans=0;
        for(int i=0;i<n-1;i++){
            ll x,y,l;
            cin>>x>>y>>l;
            G[x].push_back(Edge(y,x,y,l));
            G[y].push_back(Edge(x,x,y,l));
        }
        dfs(1);
        cout<<ans<<endl;
    }
    return 0;
}

J.HDU6447 YJJ‘s Salesman

题意

题意:一个地图,里面有最多1e5个村庄,YJJ从0,0开始走,只能向左,下,左下走,如果向左下走进一个村庄那就能获得这个村庄的价值;求最大价值;从(0,0)到(n,n);
数据范围1e9!数组装不下

思路

首先题意是求最大值,最基本的DP模型是三个方向的最大值;但是复杂度会爆炸而且也开不了那么大的数组;
1.离散化坐标;因为1e9的坐标范围太大数组装不下,但是只有1e5的村庄,所以可以把1e9离散化到1e5里面;

2.每次搜索前面的最大值;利用树状数组搜索到当前位置的J坐标之前的最大值然后加上当前值再添加进树状数组

比赛的时候离散完,想吧坐标压缩成一维的可是没想到办法所以凉凉了,其实这题不用压缩直接按照x的坐标从小到大排序,然后按照同一行从大到小排序就行了;

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod=998244353;
const int maxn=1e5+50;
const int maxm=1e5+50;
const ll inf=0x3f3f3f3f3f3f;
int N;
struct node{
    int x,y,value;
};
int cmp(node a,node b){
    if(a.x==b.x)return a.y>b.y;
    return a.x<b.x;
}
int c[maxm];
inline int lowbit(int x){return x&(-x);}
void update(int x,int p){
    for(int i=x;i<maxn;i+=lowbit(i)){
        c[i]=max(c[i],p);
    }
}
int query(int x){
    int ma=0;
    for(int i=x;i>0;i-=lowbit(i)){ma=max(ma,c[i]);}
    return ma;
}
int main()
{
    std::ios::sync_with_stdio(false);
    std::cin.tie(0);
    std::cout.tie(0);
    int t;
    cin>>t;
    while(t--){
        int n;
        cin>>n;
        vector<node>ve;
        vector<int>k;
        k.push_back(-1);
        memset(c,0,sizeof(c));
        for(int i=0;i<n;i++){
            node a;
            cin>>a.x>>a.y>>a.value;
            ve.push_back(a);
            k.push_back(a.y);
        }
        sort(k.begin(),k.end());
        sort(ve.begin(),ve.end(),cmp);
        k.erase(unique(k.begin(),k.end()),k.end());
        N=k.size();
        int anw=0;
        for(int i=0;i<n;i++){
            int ans=lower_bound(k.begin(),k.end(),ve[i].y)-k.begin();
            int cnt=query(ans-1);
            cnt+=ve[i].value;
            update(ans,cnt);
            anw=max(anw,cnt);
        }
        cout<<anw<<endl;
    }
    return 0;
}

2018中国大学生程序设计竞赛 - 网络选拔赛

标签:one   for   font   个数   ras   模型   优先   大学   节点   

原文地址:https://www.cnblogs.com/luowentao/p/10332188.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!