zoukankan      html  css  js  c++  java
  • 题解-CF1350,CF1349

    CF1350

    A Orac and Factors

    我们发现如果 (n) 是偶数,则 (f(n) = 2),而它加上 (2) 之后还会是偶数,所以它只会一直加 (2),加 (k)(2)

    如果它是奇数,则它不会有偶因数,所以它的最小因子一定是奇数。又因为奇数加奇数一定是偶数,所以我们可以暴力跑一遍(即 (O(sqrt{n})) 枚举因子),然后就变成了上面那种情况。

    大概就是这样了。

    #include <iostream>
    #include <cstdio>
    using namespace std;
    typedef long long ll;
    ll t;
    ll n, k, f;
    ll Find(ll x) {
    	for (ll i = 2; i * i <= x; i++) {
    		if (x % i == 0) return i;
    	}
    	return x;
    }
    int main() {
    	cin >> t;
    	while (t--) {
    		cin >> n >> k;
    		f = Find(n);
    		if (f == 2) {
    			n += 2 * k;
    		} else {
    			n += f;
    			n += 2 * (k - 1);
    		}
    		cout << n << "
    ";
    	}
    	return 0;
    }
    

    B Orac and Models

    我来写一个思路基本和官方题解相同但又有一点不一样的题解。

    也是 dp+枚举因数。

    设计子状态 (f[i]) 待表选第 (i) 个数可以得到的最长序列。

    转移方程就是对于每个 (j | i)(s[i]>s[j])(f[i] = max(f[i], f[j]+1))。初始化所有 (f)(1)

    注意这里的 (j eq i)

    然后答案就是 (max(f[i]))(i in [1, n])

    这道题也是非常的水的。

    #include <iostream>
    #include <cstdio>
    using namespace std;
    int t;
    int n;
    int s[100010];
    int f[100010], ans;
    int main() {
    	cin >> t;
    	while (t--) {
    		ans = 0;
    		cin >> n;
    		for (int i = 1; i <= n; i++) f[i] = 1;
    		for (int i = 1; i <= n; i++) {
    			cin >> s[i];
    		}
    		for (int i = 1; i <= n; i++) {
    			if (i != 1) {
    				if (s[i] > s[1]) {
    					f[i] = max(f[i], f[1] + 1);
    				}
    			}
    			for (int j = 2; j * j <= i; j++) {
    				if (i % j) continue;
    				if (s[i] > s[j]) {
    					f[i] = max(f[i], f[j] + 1);
    				}
    				if (s[i] > s[i / j]) {
    					f[i] = max(f[i], f[i / j] + 1);
    				}
    			}
    		}
    		for (int i = 1; i <= n; i++) {
    			ans = max(ans, f[i]);
    		}
    		cout << ans << "
    ";
    	}
    	
    	return 0;
    }
    

    CF1349

    B Orac and Medians

    这道题其实就是几个美妙的性质。

    首先如果序列里没有出现 (k),则一定是 (no)

    我们再证如果有两个连续的 (k) 出现,怎一定可以把另外两个相邻的数变成 (k),这样就可以把所有的数都变成 (k) 了。

    如果一个 (k) 的旁边出现了一个比 (k) 大的数,那么 (k) 可以把它变成 (k),就成了上面那种情况。

    所以我们现在就要让尽量多的大于等于 (k) 的数出现。

    我们发现如果三个连续的数中有两个大于等于 (k) 的数,那么就可以把第三个数变成大于等于 (k) 的。所以如果存在三个数满足上述条件,则可以完成。

    如果不存在呢?那用更多的数也凑不出比 (k) 大的,所以就不可能了。

    #include <iostream>
    #include <cstdio>
    using namespace std;
    int t;
    int n, k;
    int a[100010];
    int main() {
    	cin >> t;
    	while (t--) {
    		cin >> n >> k;
    		bool flag = 0;
    		for (int i = 1; i <= n; i++) {
    			cin >> a[i];
    			if (a[i] == k) flag = 1;
    			if (a[i] >= k) a[i] = 1;
    			else a[i] = 0;
    		}
    		if (flag == 0) {
    			puts("no");
    			continue;
    		}
            //特判n=1和n=2
    		if (n == 1) {
    			puts("yes");
    			continue;
    		}
    		if (n == 2) {
    			if (a[1] && a[2]) {
    				puts("yes");
    			} else {
    				puts("no");
    			}
    			continue;
    		}
    		bool ans = 0;
    		for (int i = 1; i + 2 <= n; i++) {
    			if (a[i] && (a[i + 1] || a[i + 2])) {
    				ans = 1;
    				break;
    			}
    		}
    		if (a[n - 1] && a[n]) ans = 1;
    		if (ans) puts("yes");
    		else puts("no");
    	}
    	return 0;
    }
    
  • 相关阅读:
    vsync信号产生与分发
    推荐看过不错的博客及网站
    证明质数有无数个
    242 Valid Anagram
    169 Majority Element
    快速排序--quicksort
    插入排序
    选择排序
    冒泡排序
    指针函数 函数指针 回调函数
  • 原文地址:https://www.cnblogs.com/zcr-blog/p/14900943.html
Copyright © 2011-2022 走看看