Codeforces 1600 x 5 (2)

1.

原题链接

点我跳转

tag. math, number theory

题目大意

给一个长度为n的序列,且元素1-n不重复,求该序列中有多少个数是孤独的。

孤独:在这个序列里没有任意的另外的一个数与它构成的以下这3个数组成一个三角形。

\[gcd(a,b) , \frac{a}{gcd(a,b)}, \frac{b}{gcd(a,b)} \]

解题思路

  • 合数肯定不孤独,如:4,6,8,9 .......
  • 如果最大的数(就是n)是质数,那它肯定孤独。
  • 要使一个质数不孤独,得要直到n大于等于这个质数的平方。

所以预处理时,n假设为质数时:ans[i] = ans[i-1] + 1 。

如果是合数:如果sqrt(n)这个数恰好是质数,那么ans自减1。

AC_CODE

#include<bits/stdc++.h>
#define ios std::ios::sync_with_stdio(false)
#define rep(i,a,n) for (int i=a;i<=n;i++)
#define per(i,n,a) for (int i=n;i>=a;i--)
#define int long long

using namespace std;

const int N = 1e6 + 10, MOD = 1e9+7, inf = 0x3f3f3f3f;

const int MAX_N = 1e6 + 10;
int CNT, prime[MAX_N];
bool vis[MAX_N];
void make_prime() {
    CNT = 0;
    for(int i = 2; i < MAX_N; ++i) {
        if(!vis[i]) {
            prime[++CNT] = i;
            for(int j = 2; j * i < MAX_N; ++j)
                vis[i*j] = true;
        }
    }
}
int ans[N];
signed main()
{
	ios;
	cin.tie(0), cout.tie(0);
	make_prime();
	for (int i = 1 ; i < N; i++){
		if (!vis[i]) {
			ans[i] = ans[i - 1] + 1;
		} else {
			ans[i] = ans[i - 1];
			int x = sqrt(i);
			if (x * x == i && !vis[x]) {
				ans[i] --;
			}
		}
	}
	int t;
	cin >> t;
	while (t--) {
		int n;
		cin >> n;
		cout << ans[n] << '\n';
	}
    return 0;
}

2.

原题链接

点我跳转

tag. data structures, dp, math

题目大意

给一个长度为n的序列,要求找出有多少个子串的和恰好等于该子串的长度。

解题思路

求出序列的前缀和,遍历的途中查询当前得到的前缀和数值在之前已经出现多少次,答案加上次数即可。

AC_CODE

#include<bits/stdc++.h>
#define ios std::ios::sync_with_stdio(false)
#define rep(i,a,n) for (int i=a;i<=n;i++)
#define per(i,n,a) for (int i=n;i>=a;i--)
#define int long long
using namespace std;
const int N = 2e5 + 10, MOD = 1e9+7, inf = 0x3f3f3f3f;

signed main()
{	
	int T;
	cin >> T;
	while(T--)
	{
		int n;
		cin >> n;
		map<int,int>mp;
		mp[0] = 1;
		int ans = 0,pre = 0;
		for (int i = 1; i <= n ;i ++){
			char s;
			cin >> s;
			pre = pre + s - '1';
			mp[pre]++ ;
			ans += mp[pre] - 1;
		}
		cout << ans << '\n';
	}
    return 0;
}

3.

原题链接

点我跳转

tag. bitmarks, dp , brute force

题目大意

给两个序列\(a\)\(b\),长度分别为\(n\)\(m\),对序列a中的每个元素\(a_i\),取\(b\)序列中的任意一个元素 \(b_j\) ,得到\(c_i\) = \(a_i \& b_j\) 。题目要求 \(c_1|c_2|c_3| \ldots |c_{n-1}|c_n\) 最小。

过题代码

#include<bits/stdc++.h>
#define ios std::ios::sync_with_stdio(false)
#define rep(i,a,n) for (int i=a;i<=n;i++)

using namespace std;

const int N = 2e2 + 10, MOD = 1e9+7, inf = 0x3f3f3f3f;

int n,m,a[N],b[N],dp[N][1024];
signed main()
{
	cin >> n >> m;
	rep(i,1,n) cin >> a[i];
	rep(i,1,m) cin >> b[i];
	rep(i,1,m) dp[1][a[1]&b[i]] = 1;
	rep(i,2,n){
		rep(j,0,(1 << 9) - 1){
			if (dp[i-1][j]){
				rep(k,1,m){
					dp[i][j | (a[i] & b[k])] = 1;
				}
			}
		}
	}
	rep(i,0,(1 << 9) - 1){
		if (dp[n][i]){
			cout << i << '\n';
			break;
		}
	}
    return 0;
}

4.

原题链接

点我跳转

tag. two point,dp

题目大意

给一个数字\(k\)和一个01字符串,求满足条件的子串个数,这个条件是该子串中的\(1\)的个数刚好为 \(k\).

过题代码

#include<bits/stdc++.h>
#define ios std::ios::sync_with_stdio(false)
#define rep(i,a,n) for (int i=a;i<=n;i++)
#define per(i,n,a) for (int i=n;i>=a;i--)
#define int long long
#define fi first
#define se second

using namespace std;

const int N = 1e6 + 10, MOD = 1e9+7, inf = 0x3f3f3f3f;

signed main()
{
	int k;
	string s;
	cin >> k >> s;
	int l = -1, r = 0;
	int cnt = 0, n = s.size();
	int ans = 0, x = 1, y = 1;
	if (k == 0){
		for (int i = 0; i < n; i++)
			if (s[i] == '0'){
				cnt++;
			}
			else{
				ans += (1 + cnt) * cnt / 2;
				cnt = 0;
			}
		ans += (1 + cnt) * cnt / 2;
		cout << ans << '\n';
		return 0;
	} 
	for (int i = 0; i < n; i++){
		if (s[i] == '1') cnt++;
		if (cnt == k){
			r = i;
			break;
		}
	}
	if (cnt < k) return cout << "0\n" , 0;
	while(1){
		while(s[l+1] == '0'){
			x++;
			l++;
		}
		while(r + 1 < n && s[r+1] == '0'){
			y++;
			r++;
		}
		if (r >= n) break;
		ans += x * y;
		x = y = 1;
		l++; r++;
		if (r > n) break;
	}
	cout << ans << '\n';
    return 0;
}

5.

点我跳转

tag. dp

题目大意

一个字符串从0开始,01交替出现,给一个\(n\),代表该字符串的长度,求该字符串的子序列能构成01交替或者10交替的个数

过题代码

#include<bits/stdc++.h>
#define ios std::ios::sync_with_stdio(false)
#define rep(i,a,n) for (int i=a;i<=n;i++)
#define per(i,n,a) for (int i=n;i>=a;i--)
#define int long long
#define fi first
#define se second

using namespace std;

const int N = 1e6 + 10, MOD = 1e9+7, inf = 0x3f3f3f3f;
int dp[N];
signed main()
{
	int n;
	cin >> n;
	int one = 0, two = 0;
	dp[0] = 0;
	for (int i = 1; i <= n; i++){
		if (i & 1)
		{
			dp[i] = (dp[i-1] + two + 1) % MOD;
			one += (two + 1) % MOD;
		}
		else{
			dp[i] = (dp[i-1] + one + 1) % MOD;
			two += (one + 1) % MOD;
		}
	}
	cout << dp[n] << '\n';
    return 0;
}
posted @ 2020-11-01 12:40  SZyzBO  阅读(66)  评论(0)    收藏  举报