zoukankan      html  css  js  c++  java
  • #QBXT2020十一 Day1 考试题解

    (Day 1)

    T1 打扑克

    手推可以得到结果,注意特别判定(n = 1,2,3)时的情况

    经过手推,可以得到当且仅当n是奇数且0是先手,0才会获胜。

    (Code)

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #define N 100010
    using namespace std;
    char c[N];
    int T,op;
    int main()
    {
    	cin>>T;
    	while(T--)
    	{
    		scanf("%s%d",c,&op);
    		int n=strlen(c);
    		int x=c[n-1];
    		if(n==1&&x=='2')
    		{
    			if(!op) cout<<0<<endl;
    			else cout<<1<<endl; 
    		}
    		else
    		{
    			if((x-'0')%2==1&&!op) cout<<0<<endl;
    			else cout<<1<<endl;
    		}
    	}
    }
    

    T2 粉刷匠

    通过审题,能够知道,后面的操作是要把前面的操作完全覆盖的。所以我们可以倒着看这些操作,对于每一种操作,记录当前颜色(即最终颜色)并删除这一列。这样进行计算就可以了。

    (Code)

    #include <iostream>
    #include <algorithm>
    using namespace std;
    const long long maxn = 1000009;
    long long read() {
    	char c = getchar();
    	long long f = 1, tot = 0;
    	if (c == '-') { f = -1; c = getchar(); }
    	while (c >= '0' && c <= '9') {
    		tot = tot * 10 + c - '0';
    		c = getchar();
    	}
    	return tot * f;
    }
    long long n, m, k;
    long long x[maxn], y[maxn], z[maxn], totx, toty, wx, wy;//横行是x,纵列是y
    bool visx[maxn], visy[maxn];
    long long ans = 0;
    int main() {
    	n = read(), m = read(), k = read();
    	for (long long i = 1; i <= k; ++i) x[i] = read(), y[i] = read(), z[i] = read();
    	wx = n, wy = m;
    	for (long long i = k; i >= 1; --i) {
    		if (!x[i]) {
    			if (!visx[y[i]] && wy) {
    				visx[y[i]] = 1;
    				if (z[i]) ans += wy;
    				wx--;
    			}
    		} else {
    			if (!visy[y[i]] && wx) {
    				visy[y[i]] = 1;
    				if (z[i]) ans += wx;
    				wy--;
    			}
    		}
    	}
    	cout << ans << endl;
    	return 0;
    }
    

    倒序操作类似题目:(BZOJ 2054)疯狂的馒头

    T3 直线竞速

    离线算法。将所有询问按照时间顺序排序,每次对于新的询问,都用冒牌排序进行更新,从而求出第(k)的值。

    (Code)

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<vector>
    #include<queue>
    #include<cmath>
    #include<set>
    #include<map>
    #include<cstdlib>
    #include<bitset>
    #include<stack>
    #include<ctime>
    #include<fstream>
    #define dd double
    #define ll long long
    #define mp make_pair
    #define pb push_back
    #define N 7010
    #define M 1010
    using namespace std;
    int n,Q;
    struct ma
    {
    	int v,a,num;
    }w[N];
    bool cmp1(ma x,ma y)
    {
    	return x.a>y.a;
    }
    struct am
    {
    	int t,k,ans,num;
    }q[N];
    bool cmp2(am x,am y)
    {
    	return x.t<y.t;
    }
    bool cmp3(am x,am y)
    {
    	return x.num<y.num;
    }
    int main()
    {
    	cin>>n;
    	for(int i=1;i<=n;i++)
    	{
    		scanf("%d%d",&w[i].v,&w[i].a);
    		w[i].num=i;
    	}
    	cin>>Q;
    	for(int i=1;i<=Q;i++)
    	{
    		scanf("%d%d",&q[i].t,&q[i].k);
    		q[i].num=i;
    	}
    	sort(w+1,w+n+1,cmp1);
    	sort(q+1,q+Q+1,cmp2);
    	for(int i=0;i<=Q;i++)
    	{
    		for(int j=1;j<=n;j++)
    		{
    			for(int k=j;k>1;k--)
    			{
    				ll x=w[k].a+(ll)w[k].v*q[i].t;
    				ll y=w[k-1].a+(ll)w[k-1].v*q[i].t;
    				if(y<x||y==x&&w[k-1].num>w[k].num) swap(w[k-1],w[k]);
    				else break;
    			}
    		}
    		q[i].ans=w[q[i].k].num;
    	}
    	sort(q+1,q+Q+1,cmp3);
    	for(int i=1;i<=Q;i++) printf("%d
    ",q[i].ans);
    }
    

    T4 游戏luogu

    考场思路:四维(DP),但是写挂了。

    (Code)

    #include <iostream>
    #include <algorithm>
    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    using namespace std;
    const int maxn = 2009;
    int m, n;
    int a[maxn], b[maxn];
    int ans = 2147483647;
    int sa[maxn], sb[maxn];
    int f[maxn][maxn];
    int main() {
    	cin >> n >> m;
    	for (int i = 1; i <= n; ++i) cin >> a[i];
    	for (int i = 1; i <= m; ++i) cin >> b[i];
    	reverse(b + 1, b + 1 + m);
    //	for (int i = 1; i <= m; ++i) cout << b[i] << ' '; cout << endl;
    	for (int i = 1; i <= max(m, n); ++i) {
    		sa[i] = sa[i - 1] + a[i];
    		sb[i] = sb[i - 1] + b[i];
    		cout << sa[i] << ' ' << sb[i] << endl;
    	}
    	for (int i = 1; i <= n; ++i) for (int j = 1;j <= m; ++j) f[i][j] = 0x3ffff;
    	f[1][1] = 0;
    	for (int i = 1; i <= n; ++i) {
    		for (int j = 1; j <= m; ++j) {
    			for (int k = 1; k < i; ++k) {
    				for (int l = 1; l < j; ++l) {
    					printf("%d %d %d %d %d %d %d
    ", i, j, k, l, f[i][j],  (sa[i] - sa[k - 1] - (i - k + 1)) , (sb[j] - sb[l - 1] - (j - l + 1)));
    					f[i][j] = min(f[i][j], f[k][l] + (sa[i] - sa[k - 1] - (i - k + 1)) * (sb[j] - sb[l - 1] - (j - l + 1)));
    					printf("%d %d %d %d %d %d %d
    
    ", i, j, k, l, f[i][j],  (sa[i] - sa[k - 1] - (i - k + 1)) , (sb[j] - sb[l - 1] - (j - l + 1)));
    				}
    			}
    		}
    	}
    	for (int i = 1; i <= n; ++i) {
    		for (int j = 1; j <= m; ++j) cout << f[i][j] << ' '; cout << endl;
    	}
    	cout << f[n][m] << endl;
    	return 0;
    }
    

    首先,由于(s2-k2)(s1-k1)每次加上一个数都要减去1,我们可以预处理全部减一,每次的操作得分就变成s2s1。

    因为每个数都是正整数,对于数列1中的连续两段数a,c数列2中的连续两段数b,d易得(a+c)*(b+d)>=ab+cd。所以当每次两个数列都只取一个数时结果最小。

    但是,两个数列不等长,无法一对一消除。所以可能出现一对多的情况。

    综上,使用DP

    F[i][j]表示一数列已删去i个数另一数列已删去j个数时的最优解。

    [F[i][j]=min{f[i-1][j-1],f[i-1][j],f[i][j-1]}+a[i]*b[j]; ]

    当两边都只取一个数的时候

    [f[i][j]=f[i-1][j-1]+a[i]*b[j]; ]

    当其中一个数列取多个数的时候 (f[i][j]=f[i][j-1]+a[i]*b[j]) 表示a中只取一个数,b中可能取多个数,由乘法分配律(a imes (b+c)=a imes b+a imes c)得相对于f[i][j-1]增加的数为a[i]*b[j]

    初始化:f=maxlint,f[0][0]=0。

    (Code)

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<vector>
    #include<queue>
    #include<cmath>
    #include<set>
    #include<map>
    #include<cstdlib>
    #include<bitset>
    #include<stack>
    #include<ctime>
    #include<fstream>
    #define dd double
    #define ll long long
    #define mp make_pair
    #define pb push_back
    #define N 2010
    #define M 1010
    using namespace std;
    int n,m;
    int a[N],b[N];
    int f[N][N],g[N][N];
    int main()
    {
    	cin>>n>>m;
    	for(int i=1;i<=n;i++)
    	{
    		scanf("%d",&a[i]);
    		a[i]--;
    	}
    	for(int i=1;i<=m;i++)
    	{
    		scanf("%d",&b[i]);
    		b[i]--;
    	}
    	memset(f,0x3f,sizeof(f));
    	memset(g,0x3f,sizeof(g));
    	f[0][0]=g[0][0]=0;
    	for(int i=1;i<=n;i++)
    	for(int j=1;j<=m;j++)
    	{
    		int x=a[i]*b[j];
    		f[i][j]=min(f[i][j-1],min(f[i-1][j-1],g[i-1][j-1]))+x;
    		g[i][j]=min(g[i-1][j],min(f[i-1][j-1],g[i-1][j-1]))+x;
    		//cout<<i<<' '<<j<<' '<<f[i][j]<<' '<<g[i][j]<<endl;
    	}
    	int ans=min(f[n][m],g[n][m]);
    	cout<<ans<<endl;
    }
    
  • 相关阅读:
    2019牛客暑期多校训练营(第七场)- String
    2019牛客暑期多校训练营(第七场)- Governing sand
    2019 Multi-University Training Contest 6
    2019牛客暑期多校训练营(第六场)- Upgrading Technology
    2019牛客暑期多校训练营(第六场)- Shorten IPv6 Address
    2019牛客暑期多校训练营(第五场)- generator 1
    2019 Multi-University Training Contest 4
    Network POJ
    Candies POJ
    Currency Exchange POJ
  • 原文地址:https://www.cnblogs.com/Cao-Yucong/p/13758821.html
Copyright © 2011-2022 走看看