1. 程式人生 > >(寒假GYM開黑)2018-2019 ACM-ICPC Nordic Collegiate Programming Contest (NCPC 2018)

(寒假GYM開黑)2018-2019 ACM-ICPC Nordic Collegiate Programming Contest (NCPC 2018)

put def operator money node tin 自己人 n) n-1


layout: post
title: 2018-2019 ACM-ICPC Nordic Collegiate Programming Contest (NCPC 2018)
author: "luowentaoaa"
catalog: true
tags:
mathjax: true
- codeforces


傳送門

付隊!

B.Baby Bites (簽到模擬)

按照題意模擬就行了

int a[maxn];
string s;
int main()
{
    std::ios::sync_with_stdio(false);
    std::cin.tie(0);
    std::cout.tie(0);
    int n;
    cin>>n;
    int st=-1;
    int ed=-1;
    int isok=0;
    for(int i=1;i<=n;i++){
        cin>>s;
        if(s[0]=='m')a[i]=i;
        else{
            if(st==-1)st=i;
            int len=s.size();
            int num=0;
            for(int j=0;j<len;j++)num=num*10+s[j]-'0';
            a[i]=num;
            if(a[i]==0){
                ed=1;
            }
        }
    }
    for(int i=1;i<=n;i++){
        if(a[i]!=i){cout<<"something is fishy"<<endl;return 0;}

    }
    cout<<"makes sense"<<endl;
    return 0;
}

C.Code Cleanups (貪心)

題意

A[i]天會出現一個垃圾,如果不清掃每天都會+1個垃圾.不能超過20個垃圾不清掃,問你最少清掃幾次

題解

直接貪心取就完事了

int a[maxn];
int vis[maxn];
int main()
{
    std::ios::sync_with_stdio(false);
    std::cin.tie(0);
    std::cout.tie(0);
    int n;
    cin>>n;
    for(int i=1;i<=n;i++)cin>>a[i],vis[a[i]]=1;
    int ans=0,now=0,cnt=0;
    for(int i=1;i<=365;i++){
        now+=cnt;
        if(now>=20)ans++,now=cnt=0;
        if(vis[i])cnt++;
    }
    if(now||cnt)ans++;
    cout<<ans<<endl;
    return 0;
}

E.Explosion Exploit (記憶化搜索)

題意

給定N個自己人,M個敵人。以及每個人的血量ai。系統一共發起K次攻擊,每次隨機選擇一個人物進行攻擊,被攻擊後血量少1,血量為0的不再考慮。問最後敵人都被殺死的概率。 (N,M<=5 ,ai<=6,K<=100)

題解

用位數模擬血量的人數,最多12位,所以數組開不下,只能用map儲存,保存每個血量/國營的人數,概率就是,射中這個人的射中這個人的概率*射中這個人能全部殺掉的概率;

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod=998244353;
const int maxn=1e5+50;
const int logmaxn=20;
const ll inf=0x3f3f3f3f3f3f3f3fLL;
map<ll,double>mp;
ll a[2][8];

int n,m,d;
ll get(){
    ll ans=0;
    for(int i=1;i<=6;i++)ans=ans*10+a[1][i];
    for(int i=1;i<=6;i++)ans=ans*10+a[0][i];
    return ans;
}
double dfs(ll sta,int num){
    if(mp.count(sta))return mp[sta];
    if(sta<1000000)return 1;
    if(num==0)return 0;
    int sum=0;
    for(int i=0;i<2;i++)for(int j=1;j<=6;j++)sum+=a[i][j];
    double ans=0;
    for(int i=0;i<2;i++)
    for(int j=1;j<=6;j++){
        if(!a[i][j])continue;
        a[i][j]--;a[i][j-1]++;
        ll nex=get();
        double res=dfs(nex,num-1);
        a[i][j]++;a[i][j-1]--;
        ans+=(double)(a[i][j]*1.0/sum*1.0)*res*1.0;
    }
    mp[sta]=ans;
    return ans;
}
int main()
{
    std::ios::sync_with_stdio(false);
    std::cin.tie(0);
    std::cout.tie(0);
    cin>>n>>m>>d;
    for(int i=0;i<2;i++){
        int k=(i==0?n:m);
        for(int j=0;j<k;j++){
            int p;cin>>p;a[i][p]++;
        }
    }
    cout<<fixed<<setprecision(8)<<dfs(get(),d)<<endl;
    return 0;
}

H.House Lawn ()

solve by 許老師

#include<bits/stdc++.h>
#define db double
#define ll long long
using namespace std;
const int maxn=1e6+6,inf=1e9;
char str[1005];
struct node
{
    char s[65];
    int id,p;
    bool operator<(const node&t)const
    {
        if(p==t.p)return id<t.id;
        return p<t.p;
    }
}a[105];
void gao(int cur,int &pri,int &c,int &t,int &r)
{
    int n=strlen(str),i=0;
    pri=c=t=r=0;
    while(str[i]!=',')i++;
    i++;
    while(str[i]!=',')
    pri=pri*10+str[i++]-'0';i++;
    while(str[i]!=',')
    c=c*10+str[i++]-'0';i++;
    while(str[i]!=',')
    t=t*10+str[i++]-'0';i++;
    while(i<n)
    r=r*10+str[i++]-'0'; 
}
int main()
{
    int e,m,pri,c,t,r,v,n=10080,cnt=0;
    cin>>e>>m;
    getchar();
    for(int i=1;i<=m;i++)
    {
        gets(str);
        gao(i,pri,c,t,r);
        v=n/(t+r)*t*c;
        if(v<e)
        {
            int tmp=n%(t+r);
            db v1=(db(e)-v)/c,v2=tmp-v1;
            if(v1<=(db)t)
            if(v1*r<=v2*t)v=e;
        }
        if(v>=e)
        {
            a[++cnt].p=pri; a[cnt].id=i;
            int len=strlen(str),j=0;
            while(str[j]!=',')
            a[cnt].s[j]=str[j],j++;
            a[cnt].s[j]='\0';
        }
    }
    sort(a+1,a+1+cnt);
    if(cnt==0)puts("no such mower");
    else
    {
        int i=1;
        while(1)
        {
            printf("%s\n",a[i++].s);
            if(i>cnt||a[i].p>a[i-1].p)break;    
        }
    }
}

I.Intergalactic Bidding (高精度)

題意

給出N個高精度數,表示N個人對應的數字,滿足每個人的數字大於等於前面一個人的兩倍,以及S。 輸出winners,一個人是winner,當且僅當他存在一個集合裏,這個集合是和是S。

題解

首先第一眼是背包問題,但是發現這個數字太大沒辦法開數組背包;於是註意到兩倍這個關系

模擬一下二進制,從後往前,一個數字從後往前,尋找她的二進制位的過程你就會知道怎麽做了

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod=998244353;
const int maxn=1e6+50;
const ll inf=0x3f3f3f3f3f3f3f3fLL;
string s;
int cmp(string a,string b){
    if(a.length()>b.length())return true;
    else if(a.length()<b.length())return false;
    else return a>=b;
}
bool vis[1100];
struct node{
    string name;
    string money;
}my[1100];
bool cmpp(node a,node b){
    if(a.money.size()>b.money.size())return true;
    else if(a.money.size()<b.money.size())return false;
    else return a.money>b.money;
}
string sub(string a,string b){
    string ans="";
    reverse(a.begin(),a.end());
    reverse(b.begin(),b.end());
    int len1=a.length(),len2=b.length();
    int pre=0;
    for(int i=0;i<len2;i++){
        int now=a[i]-b[i];
        if(now<0)a[i+1]--,now=10+now;
        ans+=(char)(now+'0');
    }
    for(int i=len2;i<len1;i++){
        int num=a[i]-'0';
        if(num<0){
            num+=10;
            a[i+1]--;
        }
        ans+=(char)(num+'0');
    }
    while(ans.size()>1&&ans.back()=='0')ans.pop_back();
    reverse(ans.begin(),ans.end());
    return ans;
}
int main()
{
    std::ios::sync_with_stdio(false);
    std::cin.tie(0);
    std::cout.tie(0);
    int n;
    cin>>n;
    cin>>s;
    for(int i=1;i<=n;i++){
        cin>>my[i].name>>my[i].money;
    }
    int num=0;
    sort(my+1,my+1+n,cmpp);
    for(int i=1;i<=n;i++){
        if(cmp(s,my[i].money)){
            s=sub(s,my[i].money);
            vis[i]=1;
            num++;
        }
    }
    if(s=="0"){
        cout<<num<<endl;
        for(int i=1;i<=n;i++){
            if(vis[i])cout<<my[i].name<<endl;
        }
    }
    else{
        cout<<"0"<<endl;
    }
    return 0;
}

J.Jumbled String (構造題)

題意

solve by 付隊

給你00,01,10,11子序列的數量a,b,c,d。 讓你根據信息還原一個字符串

題意

由00和11的數量,我們可以得到字符串中0和1的數量x和y,然後取湊即可, 註意00數量為0時,x可能為0,也可能為1,其它情況下,x唯一; y同理。

假設得到了x,y。 我們可以試著構造一個形如11111...0001000....1111的串,即中間可以夾雜一個1。

#include<bits/stdc++.h>
#define ll long long
#define rep(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
const int maxn=3010;
const int Mod=1e9+7;
map<int,int>mp;
bool check(int A,int D,int B,int C)// 0,1
{
    if(1LL*A*D!=1LL*B+C) return false;
    if(A==0&&B==0&&C==0){
        rep(i,1,D) putchar('1'); return true;
    }
    if(D==0&&B==0&&C==0){
        rep(i,1,A) putchar('0'); return true;
    }
    int num=B/A,rem=B%A;
    rep(i,1,D-num-(rem!=0)) putchar('1');
    rep(i,1,A) {
        putchar('0');
        if(rem==i) putchar('1');
    }
    rep(i,1,num) putchar('1');
    return true;
}
int main()
{
    int A,B,C,D;
    rep(i,1,44721){
       int tmp;
       if(i&1) tmp=(i-1)/2*i;
       else tmp=i/2*(i-1);
       mp[tmp]=i;
    }
    scanf("%d%d%d%d",&A,&B,&C,&D);
    if(mp[A]==0) return puts("impossible"),0;
    if(mp[D]==0) return puts("impossible"),0;
    if(check(mp[A],mp[D],B,C)) return 0;
    if(A==0&&check(0,mp[D],B,C)) return 0;
    if(D==0&&check(mp[A],0,B,C)) return 0;
    if(A==0&&D==0&&check(0,0,B,C)) return 0;
    puts("impossible");
    return 0;
}

K.King‘s Colors (容斥)

題意

給你N,K,一棵大小為N的樹,求剛好染K種色,而且相鄰邊顏色不同的方案數。

題解

solve by 付隊

#include<bits/stdc++.h>
#define ll long long
#define rep(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
const int maxn=3010;
const int Mod=1e9+7;
int C[maxn][maxn],N,K,ans;
int qpow(int a,int x)
{
    int res=1; while(x){
        if(x&1) res=(ll)res*a%Mod;
        a=(ll)a*a%Mod; x>>=1;
    } return res;
}
int main()
{
    rep(i,0,2500) C[i][0]=C[i][i]=1;
    rep(i,1,2500)
      rep(j,1,i) C[i][j]=(C[i-1][j-1]+C[i-1][j])%Mod;
     scanf("%d%d",&N,&K);
    rep(i,2,N){
        int u; scanf("%d",&u);
    }
    for(int i=K;i>=2;i--){
        if((K-i)%2==0){
            (ans+=(ll)i*qpow(i-1,N-1)%Mod*C[K][i]%Mod)%=Mod;
        }
        else {
            ans=((ans-(ll)i*qpow(i-1,N-1)%Mod*C[K][i]%Mod)%Mod+Mod)%Mod;
        }
    }
    printf("%d\n",ans);
    return 0;
}

(寒假GYM開黑)2018-2019 ACM-ICPC Nordic Collegiate Programming Contest (NCPC 2018)