• (寒假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::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]='';
    		}
    	}
    	sort(a+1,a+1+cnt);
    	if(cnt==0)puts("no such mower");
    	else
    	{
    		int i=1;
    		while(1)
    		{
    			printf("%s
    ",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
    ",ans);
        return 0;
    }
    
  • 相关阅读:
    vi 编辑器使用技巧
    sql____001
    PL/sql 启动时出现:NLS_LANG在客户端不能确定,字符集转变将造成不可预期的后果
    oracle数据库只查询前n条
    Linux下统计当前文件夹下的文件个数、目录个数
    oracle链接指定实例
    nmon的安装和使用
    jmeditor与CKEditor4x整合的BUG
    Word图片上传控件卸载教程-Xproer.WordPaster
    ScreenCapture手动卸载教程-Xproer.ScreenCapture
  • 原文地址:https://www.cnblogs.com/luowentao/p/10349459.html
Copyright © 2020-2023  润新知