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;
}

浙公网安备 33010602011771号