B-最少剩几个?_牛客小白月赛98 (nowcoder.com)
思路
奇数+偶数 = 奇数;奇数*偶数 = 奇数
所以在既有奇数又有偶数时,两者结合可以同时删除
先分别统计奇数,偶数个数
若偶个数大于奇个数,答案是偶个数-奇个数
若奇个数大于偶个数,奇数个数减去偶个数再对2取模
ac代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0)
int main()
{
IOS;
int n,ans;
int ji=0,ou=0;
cin>>n;
vector<ll>a(n);
for(int i=0;i<n;i++)
{
cin>>a[i];
if(a[i] & 1) ji++;
else ou++;
}
if(ou>ji) ans=ou-ji;
else{
if((ji-ou)%2) ans=1;
else ans=0;
}
cout<<ans<<endl;
return 0;
}
C-两个函数_牛客小白月赛98 (nowcoder.com)
(超时问题如何解决)
初始代码(超时)
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0)
int main()
{
IOS;
ll q,a,x;
cin>>q;
for(int i=0;i<q;i++)
{
ll ans=0;
cin>>a>>x;
if(x==1) ans=(a*x)%998244353;
else{
for(int i=1;i<x;i++)
{
ans+=(a*(a%998244353*i)%998244353)%998244353;
ans%=998244353;
}
}
ans%=998244353;
cout<<ans<<endl;
}
return 0;
}
解决思路
- 快速幂
时间复杂度是 O(log n),相比于直接进行指数运算,大大提高了计算效率
快速幂代码
int FastPow(int a,int x,int mod)
{
int ans = 1;
a%=mod;
while(x)
{
if(x&1) ans=(ans*a)%mod;
a= (a*a)%mod;
x>>=1;
}
return ans;
}
- 递推式
因为是求和过程,可以用递推式
ac代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0)
ll mod=998244353;
int main()
{
IOS;
ll q,a,x;
cin>>q;
for(int i=0;i<q;i++)
{
ll ans=0;
cin>>a>>x;
if(x==1) ans=a%mod;
else
{
a = a*a %mod;
ans=(x-1)*x/2 %mod *a %mod;
}
cout<<ans<<endl;
}
return 0;
}
D-切割 01 串 2.0_牛客小白月赛98 (nowcoder.com)
思路:
- 前缀和
记录在索引的每一个位置处之前,0或1的个数
2.dp
dp[i][j]
表示考虑前 i
个字符时,最多可以进行多少次切割;对于每个长度 len
,遍历所有可能的切割起点 l
,使得 l + len - 1
不超过序列的长度;对于每个起点 l
,计算可能的切割终点 r;
对于每个起点 l
和终点 r
,遍历所有可能的切割分割点 k
,使得 k
在 l
和 r
之间;
动态规划过程的关键在于,通过递归地考虑所有可能的切割方式,并使用前缀和数组来快速计算分割点 k
两侧的子串中0和1的累计数量。通过这种方式,算法能够高效地找到满足条件的切割次数的最大值
代码
#include<bits/stdc++.h>
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
using namespace std;
/*
算法:区间DP + 前缀和 O(N*N*N)
数据结构:s0,s1前缀和数组 + 二维dp[l][r]
*/
const int N = 510;
int s0[N], s1[N];
int dp[N][N];
void solve() {
int n, L, R;
string s;
cin >> n >> L >> R >> s;
s = " " + s;
for (int i = 1; i <= n; i ++ )
s0[i] = s0[i - 1] + (s[i] == '0'),
s1[i] = s1[i - 1] + (s[i] == '1');
for (int len = 1; len <= n; len ++ )
for (int l = 1; l <= n; l ++ )
{
int r = l + len - 1;
if (r > n) break;
for (int k = l; k < r; k ++ )
{
int c0 = s0[k] - s0[l - 1];
int c1 = s1[r] - s1[k];
if (L <= abs(c0 - c1) && abs(c0 - c1) <= R)
dp[l][r] = max(dp[l][r], 1 + dp[l][k] + dp[k + 1][r]);
}
}
cout << dp[1][n] << '\n';
}
signed main() {
IOS;
int t = 1;
// cin >> t;
while (t--) {
solve();
}
return 0;
}