zoukankan      html  css  js  c++  java
  • Educational Codeforces Round 71 (Rated for Div. 2)

    Solutions


    A. There Are Two Types Of Burgers

    题意:
    做一个(A)需要两个(b)和两个(p),能卖(h)元;做一个(B)需要两个(b)和两个(f),能卖(c)元。给出(b,p,f)的数量,求最多卖多少元。
    思路:
    比赛的时候用循环搞了,判断(h,c)的大小关系,决定先做什么。也可以(b=b/2),然后判断大小,每次取最小值,利润直接算,然后更新(b),再进行一次。

    //#define DEBUG
    #include<bits/stdc++.h>
    using namespace std;
    #define lson (rt<<1)
    #define rson (rt<<1|1)
    const int N=100010;
    const int inf=0X3f3f3f3f;
    const long long INF = 0x3f3f3f3f3f3f3f3f;
    const double eps = 1e-6;
    const double pi = acos(-1.0);
    const int mod = 1000000007;
    typedef long long ll;
     
    int main() {
    	#ifdef DEBUG
    	freopen("in.txt","r",stdin);
    	#endif
        int _,b,p,f;
        double h,c;
        ll ans;
        for(scanf("%d",&_);_;_--) {
            scanf("%d%d%d%lf%lf",&b,&p,&f,&h,&c);
            ans=0;
            if(h>c) {
                while(b>=2&&p) {
                    ans+=h;
                    b-=2;
                    p--;
                }
                while(b>=2&&f) {
                    ans+=c;
                    b-=2;
                    f--;
                }
            } if(h<c) {
                while(b>=2&&f) {
                    ans+=c;
                    b-=2;
                    f--;
                }
                while(b>=2&&p) {
                    ans+=h;
                    b-=2;
                    p--;
                }
            } else {
                int zhi=p+f;
                while(b>=2&&zhi) {
                    ans+=h;
                    b-=2;
                    zhi--;
                }
            }
            printf("%lld
    ",ans);
        }
    }
    
    //#define DEBUG
    #include<bits/stdc++.h>
    using namespace std;
    const int N=100010;
    const int inf=0X3f3f3f3f;
    const long long INF = 0x3f3f3f3f3f3f3f3f;
    const double eps = 1e-6;
    const double pi = acos(-1.0);
    const int mod = 1000000007;
    typedef long long ll;
     
    int _;
    int b,p,f;
    int h,c;
     
    int main() {
    	#ifdef DEBUG
    	freopen("in.txt","r",stdin);
    	#endif
    	for (scanf("%d",&_);_;_--) {
    		scanf("%d%d%d%d%d",&b,&p,&f,&h,&c);
    		ll ans=0;
    		b/=2;
    		if (h>c) {
    			int x=min(b,p);
    			ans+=x*h;
    			b-=x,p-=x;
    			int y=min(b,f);
    			ans+=y*c;
    		} else {
    			int x=min(b,f);
    			ans+=x*c;
    			b-=x,f-=x;
    			int y=min(b,p);
    			ans+=y*h;
    		}
    		printf("%lld
    ",ans);
    	}
    }
    

    B. Square Filling

    题意:
    给出一个(01)矩阵(A),让你用一个全(0)矩阵(B),通过每次选(2 imes2)的子矩阵设值为(1),把(B)变为(A),可以的话,输出你选的子矩阵的左上角坐标。
    思路:
    范围不大,直接枚举(1)的位置,判断周围是否存在全(1)子矩阵。
    题解思路是存在子矩阵乘积大于0的,就全部设置为(2),然后一直进行,如果最后还有(1),说明不行。

    #include <bits/stdc++.h>
    #define lowbit(x) (x)&(-x)
    #define srand() srand(time(0))
    #define pi acos(-1.0)
    #define printftime() printf("Time used = %.2f
    ",(double)clock()/CLOCKS_PER_SEC)
    using namespace std;
    typedef long long ll;
    int a[100][100];
    int flag[100][100];
    struct len {
    	int l,r;
    }ans[100000];
    int main()
    {
    	int n,m,cnt=1;int f=0;
    	scanf("%d%d",&n,&m);
    	for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)scanf("%d",&a[i][j]);
    	for(int i=1;i<=n;i++){
    		for(int j=1;j<=m;j++){
    			if(a[i][j]){
    				if(a[i-1][j-1]&&a[i-1][j]&&a[i][j-1]){
    					ans[cnt].l=i-1;
    					ans[cnt++].r=j-1;
    					continue ;
    				}
    				if(a[i][j-1]&&a[i+1][j]&&a[i+1][j-1]){
    					ans[cnt].l=i;
    					ans[cnt++].r=j-1;
    					continue ;
    				}
    				if(a[i+1][j+1]&&a[i+1][j]&&a[i][j+1]){
    					ans[cnt].l=i;
    					ans[cnt++].r=j;
    					continue ;
    				}
    				if(a[i-1][j]&&a[i-1][j+1]&&a[i][j+1]){
    					ans[cnt].l=i-1;
    					ans[cnt++].r=j;
    					continue ;
    				}
    				f=1;
    			}
    		}
    	}
    	if(f)puts("-1");
    	else {
    		printf("%d
    ",cnt-1);
    		for(int i=1;i<cnt;i++)printf("%d %d
    ",ans[i].l,ans[i].r);
    	}
    }
    
    //#define DEBUG
    #include<bits/stdc++.h>
    using namespace std;
    const int N=100010;
    const int inf=0X3f3f3f3f;
    const long long INF = 0x3f3f3f3f3f3f3f3f;
    const double eps = 1e-6;
    const double pi = acos(-1.0);
    const int mod = 1000000007;
    typedef long long ll;
     
    int n, m;
    int a[100][100];
     
    int main() {
    	#ifdef DEBUG
    	freopen("in.txt","r",stdin);
    	#endif
    	scanf("%d%d", &n, &m);
    	for (int i = 1; i <= n; i++) {
    		for (int j = 1; j <= m; j++) 
    			scanf("%d", &a[i][j]);
    	}	
    	vector<pair<int, int> > ans;
    	for (int i = 1; i < n; i++) {
    		for (int j = 1; j < m; j++) {
    			if (a[i][j] * a[i][j + 1] * a[i + 1][j] * a[i + 1][j + 1] > 0 ) {
    				a[i][j] = a[i][j + 1] = a[i + 1][j] = a[i + 1][j + 1] = 2;
    				ans.push_back({i, j});
    			}
    		}
    	}
    	bool ok=true;
    	for (int i = 1; i <= n; i++) {
    		for (int j = 1; j <= m; j++) {
    			if (a[i][j] == 1) {
    				ok = false; break;
    			}
    		}
    	}
    	if (!ok) puts("-1");
    	else {
    		printf("%d
    ", (int)ans.size());
    		for (int i = 0; i < (int)ans.size(); i++) {
    			printf("%d %d
    ", ans[i].first, ans[i].second);
    		}
    	}
    	return 0;
    }
    

    C. Gas Pipeline

    题意:
    给一条公路用(01)字符串表示,有十字路口用(1)表示,现在要架管道,十字路口的时候,管道必须在高度为(2)的位置,其他位置高度可以为(1),管道同时需要支架,现给出(01)字符串,让你给公路架管道,保证开始和结束都是高度为(1)的管道。给出单位长度管道的花费和单位高度支架的花费,求架完公路的最小花费。

    思路:
    很容易想到贪心,处理出连续(0)序列的长度,(0)的位置可能不下降,所以判断一下下降与不下降的花费,选择较小的。
    (dalao)好像都是动态规划写的。(dp[i][0/1])表示(i)位置右边支架为(0/1)的最小花费,转移的话就,

    [dp[i][0/1]= egin{cases} dp[i][0]=min(dp[i-1][0]+a, dp[i-1][1]+2{ast}a)+b, & ext{if s[i]=='0'}\ dp[i][1]=min(dp[i-1][0]+2{ast}a, dp[i-1][1]+a)+2{ast}b, & ext{if s[i]=='0'}\ dp[i][1]=dp[i-1][1]+a+2{ast}b, & ext{if s[i]=='1'}\ dp[i][0]=INF,& ext{if s[i]=='1'} end{cases} ]

    (s[i]=1)的时候,右边支架高度只能为2,所以(dp[i][0]=INF),并且只能由(d[i-1][1])转移得到,因为左边支架高度也只能为(2)。初始(dp[0][0]=b,dp[0][1]=INF),因为左边由高度为(1)开始的。答案即为(dp[n][0])

    //#define DEBUG
    #include<bits/stdc++.h>
    using namespace std;
    #define lson (rt<<1)
    #define rson (rt<<1|1)
    const int N=100010;
    const int inf=0X3f3f3f3f;
    const long long INF = 0x3f3f3f3f3f3f3f3f;
    const double eps = 1e-6;
    const double pi = acos(-1.0);
    const int mod = 1000000007;
    typedef long long ll;
     
    char s[2*N];
    ll d[2*N];
     
    int main() {
    	#ifdef DEBUG
    	freopen("in.txt","r",stdin);
    	#endif
        int _,len;
        ll a,b;
        for(scanf("%d",&_);_;_--) {
            scanf("%d%lld%lld",&len,&a,&b);
            scanf("%s",s+1);
            d[len+1]=0;
            for(int i=len;i>=1;i--) {
                if(s[i]=='1') d[i]=0;
                else d[i]=d[i+1]+1;
            }
            //for(int i=1;i<=len;i++) printf("%d",d[i]);
            int op=0; //下降态
            ll sum=0;
            ll cnt=0; // 支柱:0但不下降
            for(int i=1;i<=len;i++) {
                if(s[i]=='0') {
                    if(op) {
                        if(2*a-d[i]*b+b<=0||i+d[i]-1==len) { //下降
                            if(i+d[i]-1==len) { //最后下
                                sum+=(d[i]+2)*a;
                                cnt+=2*b;
                                cnt+=d[i]*b;
                            } else { //中间下
                                sum+=(d[i]+1)*a;
                                cnt+=(d[i]-1)*b;
                                cnt+=2*b;
                            }
                            op=!op;
                        } else { // 不下降
                            sum+=d[i]*a;
                            cnt+=d[i]*2*b;
                        }
                    } else {
                        if(i+d[i]-1!=len) {
                            sum+=(d[i]-1)*a;
                            cnt+=d[i]*b;
                        } else {
                            sum+=d[i]*a;
                            cnt+=(d[i]+1)*b;
                        }
                    }
                    i=i+d[i]-1;
                } else {
                    if(op) {
                        sum+=a;
                    } else {
                        sum+=2*a;
                        op=!op;
                    }
                    cnt+=2*b;
                }
                //printf("i=%d   %lld  **** %lld
    ",i,sum,cnt);
            }
            sum=sum+cnt;
            printf("%lld
    ",sum);
        }
    }
    
    //#define DEBUG
    #include<bits/stdc++.h>
    using namespace std;
    const int N = 100010;
    const int inf = 0X3f3f3f3f;
    const long long INF = 0x3f3f3f3f3f3f3f3f;
    const double eps = 1e-6;
    const double pi = acos(-1.0);
    const int mod = 1000000007;
    typedef long long ll;
     
    char s[2*N];
    ll dp[2*N][2];
    int _;
    int n;
    ll a, b;
     
    int main() {
        #ifdef DEBUG    
        freopen("in.txt", "r", stdin);
        #endif
        for (scanf("%d", &_); _; _--) {
            scanf("%d %lld %lld", &n, &a, &b);
            scanf("%s", s+1);
            dp[0][0] = b; dp[0][1] = INF;
            for (int i = 1; i <= n; i++) {
                if (s[i] == '0') {
                    dp[i][1] = min(dp[i - 1][1] + a + 2 * b, dp[i - 1][0] + 2 * a + 2 * b);
                    dp[i][0] = min(dp[i - 1][1] + 2 * a + b, dp[i - 1][0] + a + b);
                } else {
                    dp[i][0] = INF;
                    dp[i][1] = dp[i - 1][1] + a + 2 * b;
                }
            }
            printf("%lld
    ", dp[n][0]);
        }
        return 0;    
    }
    

    D. Number Of Permutations

    题意:
    给出(n)个有序对((x_i,y_i)),如果一组有序对,按(x_i)排序非递减或按(y_i)排序非递减的话定义为坏的。然后问(n)的全排列生成的每组有序对有多少个好的。比如(n=3),给出((1,2),(3,2),(3,1)),那么按全排列生成的即为:
    (123 :(1,2),(3,2),(3,1))
    (132:(1,3),(3,1),(3,2))
    (vdots)
    思路:
    逆向思维,一共有(n!)种结果,定义(cnt_1)为按(x_i)排序非递减的,定义(cnt_2)为按(y_i)排序非递减的,定义(cnt_{12})(x_i和y_i)同时非递减的。那么答案就是(n!-cnt_1-cnt_2+cnt_{12})
    (cnt_1)的求法:假设这么一个序列:(1,2,1,3),全排列后只有两个非递减的,即(2!)。再比如:(1,2,3,2,1),全排列后有(2! {ast} 2!)个非递减的。因为(1、2)重复。所以(cnt_1)就出来了。(cnt_2)同理。
    (cnt_{12})的求法:我们可以先按(x_i)排序再按(y_i)排序,同样也是统计重复的个数。但最后要检查是否满足(y_i)非递减。

    //#define DEBUG
    #include<bits/stdc++.h>
    using namespace std;
    const int N = 100010;
    const int inf = 0X3f3f3f3f;
    const long long INF = 0x3f3f3f3f3f3f3f3f;
    const double eps = 1e-6;
    const double pi = acos(-1.0);
    const int mod = 998244353;
    typedef long long ll;
     
    pair<int, int> d[3 * N];
    map<int, int> a, b;
    map<pair<int, int>, int> ab;
    int n;
    int fac[3 * N];
     
     
    int main() {
        #ifdef DEBUG
        freopen("in.txt", "r", stdin);
        #endif
        scanf("%d", &n);
        fac[0] = 1;
        for (int i = 1; i <= n; i++) {
            fac[i] = 1ll * fac[i - 1] * i % mod;
            scanf("%d %d", &d[i].first, &d[i].second);
            a[d[i].first]++; b[d[i].second]++;
            ab[d[i]]++;       
        }
        sort(d + 1, d + n + 1);
        int sum = fac[n];
        int temp = 1;
        for (auto i : a) {
            temp = 1ll * temp * fac[i.second] % mod;
        }
        sum = (sum - temp + mod) % mod; 
        temp = 1;
        for (auto i : b) {
            temp = 1ll * temp * fac[i.second] % mod;
        }
        sum = (sum - temp + mod) % mod; 
        bool ok = true;
        temp = 1;
        for (auto i : ab) {
            temp = 1ll * temp * fac[i.second] % mod;
        }
        for (int i = 1; i < n; i++) {
            if(d[i].second > d[i + 1].second) {
                ok = false; break;
            }
        }
        if(ok) sum = (sum + temp) % mod;
        printf("%d
    ", sum);
    }
    

    E. XOR Guessing

    题意:
    猜数字(w),你每次询问(100)个数,会给你一个(w)与其中一个的异或结果(x),再次询问(100)个数,又给你一个(w)与其中一个的异或结果(y),最多询问两次,且你询问的所有数字不能重复,求(w)
    思路:
    很神奇的思路,(w)范围最多(14)位二进制,我们可以先用(100)个低(7)的数字询问,那么(x)的高(7)位就是(w)的高(7)位,再用高(7)位的数字询问,那么(y)的低(7)位就是(w)的低(7)位。(1sim100)刚好能用低(7)位表示,然后可以把(1{sim}100)的数字左移(7)位,就生成高(7)位的数字了。

    //#define DEBUG
    #include<bits/stdc++.h>
    using namespace std;
    const int N = 100010;
    const int inf = 0X3f3f3f3f;
    const long long INF = 0x3f3f3f3f3f3f3f3f;
    const double eps = 1e-6;
    const double pi = acos(-1.0);
    const int mod = 1000000007;
    typedef long long ll;
     
    int main() {
        #ifdef DEBUG
        freopen("in.txt", "r", stdin);
        #endif
        printf("?");
        for (int i = 0; i < 100; i++) printf(" %d", i + 1);
        puts("");
        fflush(stdout);
        int x;
        scanf("%d", &x);
        printf("?");
        for (int i = 0; i < 100; i++) printf(" %d", i + 1 << 7);
        puts("");
        fflush(stdout);
        int y;
        scanf("%d", &y);
        printf("! %d", (x & ~0x7f) | (y & 0x7f));
    }
    

    F. Remainder Problem

    题意:
    给出(a_1,a_2,{dots},a_{500000}),且全为(0),然后有(q)次询问,

    • 1 (x y) :(a_x + y)
    • 2 (x y)(sum_{i{in}R(x,y)}a_i)(R(x,y))(1{sim}500000)的下标(i\%x=y)的集合

    思路:
    看题解是根号分治,题目大多是(q)(N)同一数量级 ,每次修改在原数组上修改,同时用数组预处理出小于(sqrt(N))的查询(O(sqrt(N))),大于(sqrt(N))的查询就累加原数组的值(O({frac{N}{X}})),其中(X>{sqrt(N)}),所以总复杂度(O(N{sqrt(N)}))
    见代码

    //#define DEBUG
    #include<bits/stdc++.h>
    using namespace std;
    const int N = 100010;
    const int inf = 0X3f3f3f3f;
    const long long INF = 0x3f3f3f3f3f3f3f3f;
    const double eps = 1e-6;
    const double pi = acos(-1.0);
    const int mod = 1000000007;
    typedef long long ll;
     
    int q;
    int a[5*N];
    int d[710][710];
     
    int main() {
        #ifdef DEBUG
        freopen("in.txt", "r", stdin);
        #endif
        scanf("%d", &q);
        int op, x, y;
        for (int i = 1; i <= q; i++) {
        	scanf("%d %d %d", &op, &x, &y);
        	if (op == 1) {
        		a[x] += y;
        		for (int j = 1; j < 710; j++) {
        			d[j][x % j] += y; //d[j][模j的余数]
        		}
        	} else {
        		int ans = 0;
        		if (x < 710) ans = d[x][y]; // d[x][模x的余数=y]
        		else {
        			for (int j = y; j <= 500000; j += x) {
        				ans += a[j];
        			}
        		}
        		printf("%d
    ", ans);
        	}
        }
    }
    
  • 相关阅读:
    shell脚本
    数据分析学习笔记(1):工作环境以及建模理论基础
    spark复习笔记(7):sparkstreaming
    mybatis复习笔记(1):
    spark复习笔记(7):sparkSQL
    spark复习笔记(6):RDD持久化
    spark复习笔记(6):数据倾斜
    spark复习笔记(4):RDD变换
    C#重启IIS
    mongodb学习记录
  • 原文地址:https://www.cnblogs.com/ACMerszl/p/11418228.html
Copyright © 2011-2022 走看看