zoukankan      html  css  js  c++  java
  • Codeforces Round #667 Div.3 (CF1409)

    Div3,享受俯冲的快感



    A:

    给两个整数(a)(b),你可以让$a pm k (k in [1, 10]) $,求最少操作次数。


    签到题,直接给Code吧:

    /*
    	ID: Loxilante
    	Time: 2020/09/04
    	Prog: CF1409A
    	Lang: cpp
    */
    #ifdef ONLINE_JUDGE
    #pragma GCC optimize("O3")
    #endif
    #include <bits/extc++.h>
    #define rep(i, l, r) for(int i = l; i < r; i++)
    #define hrp(i, l, r) for(int i = l; i <= r; i++)
    #define rev(i, r, l) for(int i = r; i >= l; i--)
    #define ms(n, t) memset(n, t, sizeof(n))
    #define pb push_back
    #define int ll
    #ifndef JOEON
    #define D(...) 97
    #endif
    using namespace std;
    typedef long long ll;
    typedef pair<int, int> pii;
    template<typename tn = int> inline tn next(void) { tn k; cin>>k; return k; }
    signed main(void)
    {
    	#ifdef JOEON
    //		freopen("C:\Users\Joeon\Desktop\IN.txt", "r", stdin);
    //		freopen("C:\Users\Joeon\Desktop\OUT.txt", "w", stdout);
    	#endif
    	
    	ios::sync_with_stdio(false);
    	cin.tie(0);
    	
    	int T = next();
    	while(T--)
    	{
    		int a, b;
    		cin>>a>>b;
    		if (a > b) swap(a, b);
    		cout<<(b-a)/10+(!!((b-a)%10))<<endl;
    	}
    	
    	return 0;
    }
    


    B:

    给定(a, b, c, d, n),你可以进行(n)次操作,在保证(a >= c && b >= d)的情况下将(a)(b)(1),求(ab)最小值。

    被这题吊打


    一道有点思维难度的 Greedy可惜我没有思维,可以算出(a)的可能最小值(e)(b)的可能最小值(f),选可能最小值更小的减去,如果(n)还没有用完就再减另外一个。

    Code:

    /*
    	ID: Loxilante
    	Time: 2020/09/04
    	Prog: CF1409B
    	Lang: cpp
    */
    #ifdef ONLINE_JUDGE
    #pragma GCC optimize("O3")
    #endif
    #include <bits/extc++.h>
    #define rep(i, l, r) for(int i = l; i < r; i++)
    #define hrp(i, l, r) for(int i = l; i <= r; i++)
    #define rev(i, r, l) for(int i = r; i >= l; i--)
    #define ms(n, t) memset(n, t, sizeof(n))
    #define pb push_back
    #define int ll
    #ifndef JOEON
    #define D(...) 97
    #endif
    using namespace std;
    typedef long long ll;
    typedef pair<int, int> pii;
    template<typename tn = int> inline tn next(void) { tn k; cin>>k; return k; }
    signed main(void)
    {
    	#ifdef JOEON
    //		freopen("C:\Users\Joeon\Desktop\IN.txt", "r", stdin);
    //		freopen("C:\Users\Joeon\Desktop\OUT.txt", "w", stdout);
    	#endif
    	
    	ios::sync_with_stdio(false);
    	cin.tie(0);
    	
    	int T = next();
        
    	while(T--)
    	{
    		int a, b, c, d, n;
    		cin>>a>>b>>c>>d>>n;
    		int e = max(c, a-n), f = max(d, b-n);
    		if (f > e)
    			swap(a, b), swap(c, d);
    		if (b-d <= n) n -= b-d, b = d;
    		else b -= n, n = 0;
    		a -= min(a-c, n);
    		cout<<a*b<<endl;
    	}
        
        return 0;
    }
    


    C:

    给定(n, a, b),构造一个最大值最小的长度为(n)的只包含正整数的等差数列w,使得(a, b in w)


    难度不大, bf 即可,穷举在(a, b)之间元素的个数算出公差,再判断(w)中是否只包含正整数。

    Code:

    /*
    	ID: Loxilante
    	Time: 2020/09/04
    	Prog: CF1409C
    	Lang: cpp
    */
    #ifdef ONLINE_JUDGE
    #pragma GCC optimize("O3")
    #endif
    #include <bits/extc++.h>
    #define rep(i, l, r) for(int i = l; i < r; i++)
    #define hrp(i, l, r) for(int i = l; i <= r; i++)
    #define rev(i, r, l) for(int i = r; i >= l; i--)
    #define ms(n, t) memset(n, t, sizeof(n))
    #define pb push_back
    #define int ll
    #ifndef JOEON
    #define D(...) 97
    #endif
    using namespace std;
    typedef long long ll;
    typedef pair<int, int> pii;
    template<typename tn = int> inline tn next(void) { tn k; cin>>k; return k; }
    signed main(void)
    {
    	#ifdef JOEON
    //		freopen("C:\Users\Joeon\Desktop\IN.txt", "r", stdin);
    //		freopen("C:\Users\Joeon\Desktop\OUT.txt", "w", stdout);
    	#endif
    	
    	int T = next();
    	
    	clock_t InputFinished = clock();
    	
    	while(T--)
    	{
    		int n, a, b;
    		cin>>n>>a>>b;
    		rev(i, n-2, 0) if ((b-a)%(i+1) == 0)
    		{
    			int gc = (b-a)/(i+1);
    			int possiblePr = min((a-1)/gc, n-i-2);
    			int low = a-possiblePr*gc;
    			bool yes = 0;
    			rep(j, 0, n) { cout<<low<<" 
    "[j == n-1], low += gc; yes = 1; }
    			if (yes) break;
    		}
    	}
    	
    	return 0;
    }
    


    D:

    给定正整数(n,s),令(p = n+k),并且(p)的各数位之和小于等于(s),求最小的(k)

    继续被吊打

    本思路借鉴,因为写的真的好。


    我们随便口胡一个 Greedy ,ezly得出(p)肯定是(n)的某一位的进位,这样我们枚举进位的位数,这道题就ezly解决了。

    还有一些(color{orange}{Note})

    1. 不要用字符串来处理(p),我就是这样然后被虐了

    2. 这道题(p) (color{orange}{long long})装不下,所以我们可以用(color{orange}{unsigned long long})

    3. 要特判(n)位数之和是不是已经小于(s)了,如果是那么直接输出(0)就ok啦。

    Code:

    /*
    	ID: Loxilante
    	Time: 2020/09/05
    	Prog: CF1409D
    	Lang: cpp
    */
    #ifdef ONLINE_JUDGE
    #pragma GCC optimize("O3")
    #endif
    #include <bits/extc++.h>
    #define rep(i, l, r) for(int i = l; i < r; i++)
    #define hrp(i, l, r) for(int i = l; i <= r; i++)
    #define rev(i, r, l) for(int i = r; i >= l; i--)
    #define ms(n, t) memset(n, t, sizeof(n))
    #define pb push_back
    #define int ll
    #ifndef JOEON
    #define D(...) 97
    #endif
    using namespace std;
    typedef long long ll;
    typedef unsigned long long ull;
    typedef pair<int, int> pii;
    template<typename tn = int> inline tn next(void) { tn k; cin>>k; return k; }
    signed main(void)
    {
    	#ifdef JOEON
    //		freopen("C:\Users\Joeon\Desktop\IN.txt", "r", stdin);
    //		freopen("C:\Users\Joeon\Desktop\OUT.txt", "w", stdout);
    	#endif
    	
    	ios::sync_with_stdio(false);
    	cin.tie(0);
    	
    	int T = next();
    	while(T--)
    	{
    		int n, s, ans = 0, all = 0;
    		cin>>n>>s;
    
    		int temp = n;
    		while(temp) all += temp%10, temp /= 10;
    		if (all <= s) { cout<<0<<endl; continue; }
    
    		for(ull mod = 1; mod <= n; mod *= 10)
    		{
    			int bitnum = n/mod%10;
    			if (!bitnum) continue;
    				// 当前位数为0,不需要进位
    			ans += (10-bitnum)*mod;
    			n += (10-bitnum)*mod;
    				// 进位
    			all = 0;
    			temp = n;
    			while(temp) all += temp%10, temp /= 10;
    			if (all <= s) break;
    		}
    		cout<<ans<<endl;
    	}
    	
    	return 0;
    }
    


    E:

    给你(k)和二维坐标(n)个点,你要放置两个长度为(k)的平台,放好后点会掉下来,求最多的落在平台上的点的个数。


    不难发现(y)轴根本没用,因为你可以把平台放置在y轴的(- infty)上。

    也不难发现平台不重叠是最优的。

    用最朴素的 bf 思想可以想出(O(n^2))做法,先把点排序,遍历每一个点的(x)坐标,求出把平台左端放这儿能覆盖多少个点,答案是两个最大值之和。

    可惜,(O(n^2))会超时,这时我们考虑把一层(O(n))给优化,让时间复杂度低于(O(nlogn))。优化遍历点肯定无法做到,然则,我们可以优化求出把平台放这儿能覆盖多少个点。

    既然已经排好了序,那数组就满足单调性,可以考虑二分,至于代码,(color{red}{PigeonGuGuGu})

    设平台最左边覆盖的点为(e),最右边覆盖的点为(b),不难发现(e >= b),这时候满足了__two-pointer__(尺取)的性质,我们可以设两个数组(l, r)(l)表示从(point[1, t])能够覆盖的最多的点,(r)表示从(point[t, n))能够覆盖的最多的点,求出(l, r)之后,枚举(t)来求出答案。

    Code:

    /*
    	ID: Loxilante
    	Time: 2020/09/05
    	Prog: CF1409E
    	Lang: cpp
    */
    #ifdef ONLINE_JUDGE
    #pragma GCC optimize("O3")
    #endif
    #include <bits/extc++.h>
    #define rep(i, l, r) for(int i = l; i < r; i++)
    #define hrp(i, l, r) for(int i = l; i <= r; i++)
    #define rev(i, r, l) for(int i = r; i >= l; i--)
    #define ms(n, t) memset(n, t, sizeof(n))
    #define pb push_back
    #define int ll
    #ifndef JOEON
    #define D(...) 97
    #endif
    using namespace std;
    typedef long long ll;
    typedef pair<int, int> pii;
    template<typename tn = int> inline tn next(void) { tn k; cin>>k; return k; }
    const int U = 2e5+50;
    int w[U], l[U], r[U];
    signed main(void)
    {
    	#ifdef JOEON
    //		freopen("C:\Users\Joeon\Desktop\IN.txt", "r", stdin);
    //		freopen("C:\Users\Joeon\Desktop\OUT.txt", "w", stdout);
    	#endif
    	
    	ios::sync_with_stdio(false);
    	cin.tie(0);
    	
    	int T = next();
    	while(T--)
    	{
    		int n, t;
    		cin>>n>>t;
    		rep(i, 0, n) cin>>w[i];
    		rep(i, 0, n) next();
    
    		sort(w, w+n);
    		if (w[n-1]-w[0] <= t*2) { cout<<n<<endl; continue; }
    
    		int pos = 0;
    		rep(i, 0, n)
    		{
    			while(w[pos]-w[i] <= t && pos < n) pos++;
    			r[i] = pos-i;
    		}
    		rev(i, n-2, 0) r[i] = max(r[i+1], r[i]);
    		
    		pos = n-1;
    		rev(i, n-1, 0)
    		{
    			while(w[i]-w[pos] <= t && pos >= 0) pos--;
    			l[i] = i-pos;
    		}
    		rep(i, 1, n) l[i] = max(l[i-1], l[i]);
    
    		int ans = -1<<30;
    		rep(i, 0, n) ans = max(ans, l[i]+r[i+1]);
    		cout<<ans<<endl;
    	}
    
    	return 0;
    }
    


    F:

    给你一个长为(n)的字符串(a)和长为(2)的字符串(b)(k),你有(k)次机会修改(a)中元素,(a)中有(ans)个子序列为(b),求(ans)最大值。


    一道明显的3维 dp ,dp方程有亿点长(

    在字符串(a)中,(ans)实际是每个(b)之前(a)的个数之和。

    显而易见,修改(a)中字符只会修改成(b[0])(b[1]),综上,我们可以设置dp状态为(dp(i,j,k)),i代表当前下标,(j)代表已使用(s)次修改机会,(k)代表在(i)及之前出现(b[0])的次数,那我们可以对dp方程进行分类讨论 :

    1. 不修改字符,这时我们分类讨论:
      1. 当前字符为(b[0]),即(dp(i, j, k) = dp(i-1, j, k-1))
      2. 当前字符为(b[1]),即(dp(i, j, k) = dp(i-1, j, k) + k)
      3. 既不是(b[0])也不是(b[1]),即(dp(i, j, k) = dp(i-1, j, k))
    2. 修改字符,这时我们又要分类讨论:
      1. 当前字符不为(b[1]),那我们可以把它修改为(b[1]),即(dp(i, j, k) = dp(i, j-1, k-1))
      2. 当前字符不为(b[0]),那我们可以把它修改为(b[0]),即(dp(i, j, k) = dp(i, j-1, k)+k)

    还有一个小特判,当(b[0] == b[1])的时候,修改(a)中非(b[0])的哪一个字符都可以,令(p=max{k+cnt, n}),则答案为(C _p ^2),可化为(p(p-1)/2)读者自证不难


    Code:

    /*
    	ID: Loxilante
    	Time: 2020/09/06
    	Prog: CF1409F
    	Lang: cpp
    */
    #ifdef ONLINE_JUDGE
    #pragma GCC optimize("O3")
    #endif
    #include <bits/extc++.h>
    #define rep(i, l, r) for(int i = l; i < r; i++)
    #define hrp(i, l, r) for(int i = l; i <= r; i++)
    #define rev(i, r, l) for(int i = r; i >= l; i--)
    #define ms(n, t) memset(n, t, sizeof(n))
    #define pb push_back
    #define int ll
    #ifndef JOEON
    #define D(...) 97
    #endif
    using namespace std;
    typedef long long ll;
    typedef pair<int, int> pii;
    template<typename tn = int> inline tn next(void) { tn k; cin>>k; return k; }
    const int U = 2e2+50;
    int dp[U][U][U];
    signed main(void)
    {
    	#ifdef JOEON
    //		freopen("C:\Users\Joeon\Desktop\IN.txt", "r", stdin);
    //		freopen("C:\Users\Joeon\Desktop\OUT.txt", "w", stdout);
    	#endif
    	
    	ios::sync_with_stdio(false);
    	cin.tie(0);
    	
    	int n, s, ans = -1<<30;
    	cin>>n>>s;
    	string a, b;
    	cin>>a>>b;
    
    	if (b[0] == b[1])
    	{
    		int cnt = s;
    		rep(i, 0, n) cnt += a[i] == b[0];
    		cnt = min(cnt, n);
    		cout<<cnt*(cnt-1)/2<<endl;
    		return 0; 
    	}
    		
    	ms(dp, -2);
    
    	hrp(j, 0, s) dp[0][j][0] = 0;
    
    	auto chkmax = [=](auto& a, auto b)
    	{
    		if (b > a) a = b;
    	};
    
    	rep(i, 0, n) hrp(j, 0, s) rep(k, 0, n)
    	{
    		#define now dp[i+1][j][k]
    		now = dp[i][j][k];
    
    		if (a[i] == b[0] && k) chkmax(now, dp[i][j][k-1]);
    		else if (j && k) chkmax(now, dp[i][j-1][k-1]);
    		if (a[i] == b[1]) chkmax(now, dp[i][j][k]+k);
    		else if (j) chkmax(now, dp[i][j-1][k]+k);
    
    		#undef now
    	}
    
    	rep(k, 0, n) chkmax(ans, dp[n][s][k]);
    
    	cout<<ans<<endl;
    	
    	return 0;
    }
    


    完结撒花~~~

    唯一一篇AK的的题解

  • 相关阅读:
    网络编程--ASI--(ASIHTTPRequest)介绍
    iOS-多线程--介绍NSOperration
    单例模式-用GCD实现
    ios文件读取(二)
    归档、反归档
    ios文件读取
    CUICatalog: Invalid asset name supplied:
    iOS的触摸事件
    UIScrollView的属性
    exc_bad_access(code=1, address=0x789870)野指针错误
  • 原文地址:https://www.cnblogs.com/Loxilante/p/CF1409.html
Copyright © 2011-2022 走看看