Gym .101933 Nordic Collegiate Programming Contest (NCPC 2018) (寒假gym自训第四场)

(本套题算是比较温和吧,就是罚时有点高。

B .Baby Bites

题意:给出一个婴儿给出的数组,有一些数字听不清楚,让你还原,问它是否是一个从1开始的一次增加的数组。

思路:从左往右依次固定,看是否有矛盾即可。

#include<bits/stdc++.h>
#define ll long long
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define rep2(i,a,b) for(int i=a;i>=b;i--)
using namespace std;
int a[1100]; char c[10];
int main()
{
    int N; bool F=true;
    scanf("%d",&N);
    rep(i,1,N) {
        scanf("%s",c+1);
        if(c[1]==‘m‘) a[i]=-1;
        else {
            int L=strlen(c+1);
            rep(j,1,L) a[i]=a[i]*10+c[j]-‘0‘;
        }
    }
    if(a[1]==-1) a[1]=1;
    if(a[1]!=1) F=false;
    rep(i,1,N) {
        if(a[i]==-1&&a[i-1]!=-1) a[i]=a[i-1]+1;
        if(a[i]!=-1&&a[i-1]!=-1)
          if(a[i]!=a[i-1]+1) F=false;
    }
    if(F) puts("makes sense");
    else puts("something is fishy");
    return 0;
}

C .Code Cleanups

题意:给定N个物体,每个物品需要在第几天清扫。 你每次可以选择其中几个清扫,但是要满足你选择的集合拖欠的天数之和<20;问最小的清扫次数。

思路:贪心地取即可。

#include<bits/stdc++.h>
#define ll long long
#define rep(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
int a[1100];
int main()
{
    int N,ans=0; scanf("%d",&N);
    rep(i,1,N) scanf("%d",&a[i]);
    rep(i,1,N){
        int now=1,sum=0,j=i; ans++;
        while(j+1<=N&&(sum+now*(a[j+1]-a[j]))<20)
            sum+=now*(a[j+1]-a[j]),now++,j++;
        i=j;
    }
    printf("%d",ans);
    return 0;
}

E. Explosion Exploit

题意:给定N个自己人,M个敌人。以及每个人的血量ai。系统一共发起K次攻击,每次随机选择一个人物进行攻击,被攻击后血量少1,血量为0的不再考虑。问最后敌人都被杀死的概率。 (N,M<=5 ,ai<=6,K<=100)

思路:因为数据都比较小,我们可以考虑记忆化搜索,显然我们不能开10维数组来模拟,空间不够。  我们需要维护两个集合,分别是自己人的血量和敌人的血量,然后记忆话搜索。 集合我们可以用vector来表示,每次向下搜索前vector可以先排序,这样可以减很多的枝。   我的代码没用数组表示集合,用的是long long。

因为魔改了几次,所以代码比较丑。

#include<bits/stdc++.h>
#define ll long long
#define rep(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
map<ll,double>mp; int N,M,K;
int a[13],b[13],sum,FCY; ll P[20];
int c[13],cnt;
void Change(ll &x){ //集合内部排序
    ll res=0;
    for(int i=N;i>=1;i--) a[i]=x%10,x/=10;
    for(int i=M;i>=1;i--) b[i]=x%10,x/=10;
    sort(a+1,a+N+1); sort(b+1,b+M+1);
    rep(i,1,M) res=res*10+b[i],c[N+M+1-i]=b[i];
    rep(i,1,N) res=res*10+a[i],c[N+1-i]=a[i];
    cnt=0; rep(i,1,N) if(a[i]) cnt++; rep(i,1,M) if(b[i]) cnt++;
    x=res;
}
double dfs(ll Now,int D)
{
    Change(Now); int num=cnt,d[13];
    rep(i,1,N+M) d[i]=c[i];
    if(mp.find(Now)!=mp.end()) return mp[Now];
    if(Now<FCY) return mp[Now]=1.0;
    if(D==0) return mp[Now]=0.0;
    double res=0;
    rep(i,1,N+M) {
        if(d[i]==0) continue;
        d[i]--; if(d[i]==0) num--;
        res+=dfs(Now-P[i-1],D-1)/(num+(d[i]==0));
        if(d[i]==0) num++; d[i]++;
    } return mp[Now]=res;
}
int main()
{
    scanf("%d%d%d",&N,&M,&K);
    rep(i,1,N) scanf("%d",&a[i]),sum+=a[i];
    rep(i,1,M) scanf("%d",&b[i]),sum+=b[i];
    if(K>=sum) return puts("1.00000000"),0;
    ll Now=0; FCY=1; P[0]=1; cnt=N+M;
    rep(i,1,N+M) P[i]=P[i-1]*10;
    rep(i,1,M) Now=Now*10+b[i],c[N+M+1-i]=b[i];
    rep(i,1,N) Now=Now*10+a[i],FCY*=10,c[N+1-i]=a[i];
    printf("%.8lf\n",dfs(Now,K));
    return 0;
}

H .House Lawn

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。

思路:首先挖掘为何有大于等于两倍,我们发现它告诉我们每一个集合表示出来的数都是不同的,而每一个S对应的集合也是唯一的,所以要么没有winner,要么我们可以从大到小贪心地拼凑出S。

by 罗

elect Code

#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

题意: 给你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种色,而且相邻边颜色不同的方案数。

思路:一眼容斥题,我们用F(x)表示颜色大于等于x的方案数,则ans=F(K)*C(K,K) -F(K-1)*C(K,K-1)+F(K-2)*C(K,K-2)...

而这又是一棵树,所以我们从上到下染色,没给点只要和父亲颜色不同即可。 所以F(x)=x*(x-1)^(N-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;
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;
}

原文地址:https://www.cnblogs.com/hua-dong/p/10346375.html

时间: 2024-10-01 22:56:57

Gym .101933 Nordic Collegiate Programming Contest (NCPC 2018) (寒假gym自训第四场)的相关文章

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

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::syn

2017-2018 ACM-ICPC Nordic Collegiate Programming Contest (NCPC 2017)

D.Distinctive Character 看到样例,第一个反应贪心.先写了个按这一位1和0的数目多少,确定0还是1的东西.感觉不够真,又写了个尽量加到相似的比较小的串上的贪心.在和前边的那个组合一下,换了换顺序...好吧就过了13组样例...正解如下:考虑如何求出,所有2^k个状态与这n个串的最大相似度.起初的n个串的答案显然为k,那改变一个位置,相似度就改变为k-1,对于一个状态,越早算出来的相似度,越大,那么就可以直接bfs求出所有状态的最大相似度了.答案就是取最小值的状态. #inc

Nordic Collegiate Programming Contest 2015? B. Bell Ringing

Method ringing is used to ring bells in churches, particularly in England. Suppose there are 6 bells that have 6 different pitches. We assign the number 1 to the bell highest in pitch, 2 to the second highest, and so on. When the 6 bells are rung in

【离散化树状数组】Nordic Collegiate Programming Contest G.Galactic Collegiate Programming Contest

1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 int n,m; 5 const int maxn=1e5+3; 6 struct node 7 { 8 int team; 9 int num; 10 int time; 11 int id; 12 }a[maxn]; 13 int ans[maxn]; 14 int b[maxn]; 15 int c[maxn]; 16 int s[maxn

2018 Arab Collegiate Programming Contest (ACPC 2018) G. Greatest Chicken Dish (线段树+GCD)

题目链接:https://codeforces.com/gym/101991/problem/G 题意:给出 n 个数,q 次询问区间[ li,ri ]之间有多少个 GCD = di 的连续子区间. 题解:类似HDU 5726,可以先看一下这个blog:https://blog.csdn.net/u013569304/article/details/51987053 考虑离线,先预处理出[ 1,n ]之间所有的GCD,同时需要记录每种 GCD 的区间,方法是固定一个右端点R,对于区间[ L,R

(寒假开黑gym)2018 ACM-ICPC, Syrian Collegiate Programming Contest

layout: post title: (寒假开黑gym)2018 ACM-ICPC, Syrian Collegiate Programming Contest author: "luowentaoaa" catalog: true tags: mathjax: true - codeforces 传送门 付队! 许老师! Hello SCPC 2018! (签到) #include<bits/stdc++.h> using namespace std; typedef

(寒假开黑gym)2018 ACM-ICPC, Syrian Collegiate Programming Contest(爽题)

layout: post title: (寒假开黑gym)2018 ACM-ICPC, Syrian Collegiate Programming Contest(爽题) author: "luowentaoaa" catalog: true tags: mathjax: true - codeforces - DP - 状态压缩 - LCA 传送门 付队! C - Greetings! (状态压缩) 题意 给N种信件,你可以任意选择K种信封装信件,问你最少的浪费是多少 不能大的信件装

(寒假GYM开黑)2018 German Collegiate Programming Contest (GCPC 18)

layout: post title: 2018 German Collegiate Programming Contest (GCPC 18) author: "luowentaoaa" catalog: true tags: mathjax: true - codeforces 传送门 付队博客 C.Coolest Ski Route (记忆化搜索) 题意 给出一个有向图,求出一个权值最长的链, 题解 暴力dfs会超时,所以直接储存每个起点能走到的最远距离 #include<

ACM International Collegiate Programming Contest, Tishreen Collegiate Programming Contest (2018) Syria, Lattakia, Tishreen University, April, 30, 2018

ACM International Collegiate Programming Contest, Tishreen Collegiate Programming Contest (2018) Syria, Lattakia, Tishreen University, April, 30, 2018 Problem A. Can Shahhoud Solve it? Problem B. Defeat the Monsters Problem C. UCL Game Night Problem