(1)题目大意
给定你一个字符串长度为n,里面包含a,b,c,?四种符号,?号可以代替三种符号,现在问你最后构成的abc能够有多少。
(2)解题思路
对于每一个串,如果可以构成abc,那么一定是从从左到右的,那么我们可以线性递推过去,对于abc这三种字符,b能够构成有效的序列是前面的a连着,c能够构成有效的序列是前面的b连着,而对于?号,可以构成abc三类字符,因此对于每一个?号,对答案的贡献肯定是3*dp[j] + dp[j - 1]。
比如说abcabc?,最后这个问号不论是a还是b还是c都会让答案加上一倍,但是c会让答案多加上一次前面含b的,因此状态转移方程就是dp[j] = (3 * dp[j] + dp[j - 1])。
(3)代码实现
#include "bits/stdc++.h"
using namespace std;
const int N = 2e5 + 10,mod = 1e9 + 7;
long long dp[4];
void solve()
{
int n;
cin >> n;
string s;
cin >> s;
s = " " + s;
dp[0] = 1;
for(int i = 1;i < s.size();i++) {
if(s[i] == 'a') dp[1] = (dp[1] + dp[0]) % mod;
else if(s[i] == 'b') dp[2] = (dp[2] + dp[1]) % mod;
else if(s[i] == 'c') dp[3] = (dp[2] + dp[3]) % mod;
else {
for(int j = 3;j >= 1;j--) dp[j] = (3LL * dp[j] + dp[j - 1]) % mod;
dp[0] = 3LL * dp[0] % mod;
}
}
cout << dp[3] << endl;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
int T;
T = 1;
while(T --) {
solve();
}
return 0;
}
(1)题目大意
给定你一个长度为n的密码序列,规定第对于每个段,它的长度被写在它的旁边,要么在它的左边,要么在它的右边,现在问你这个序列是否正确。
(2)解题思路
对于这个问题,我们不能直接做,而是要转换思路,看看每个数若是一个长度数,那哪些序列会被他包括进去,因此对于第i个数,我们可以向左或者向右走a[i]下,表示这是他的一个合法序列,然后看他们是否能够连接上一个操作数也就是a[i] - 1或者a[i] + 1的位置,若是可以,则这个数可以作为一个长度数,因此对于这个问题我们就抽象成了看能否从0出发通过这些序列走到n。
(3)代码实现
#include "bits/stdc++.h"
using namespace std;
const int N = 2e5 + 10;
int dp[N],a[N];
void solve()
{
int n,x;
cin >> n;
memset(dp,0,sizeof(dp));
dp[0] = dp[n + 1] = 1;
for(int i = 1;i <= n;i++) {
cin >> a[i];
if(i - a[i] - 1 >= 0) dp[i] |= dp[i - a[i] - 1];
if(i + a[i] <= n) dp[i + a[i]] |= dp[i - 1];
}
if(dp[n]) cout << "YES" << endl;
else cout << "NO" << endl;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
int T;
cin >> T;
while(T --) {
solve();
}
return 0;
}
(1)题目大意
给定你六个数,分别是技能1造成的伤害,以及冷却时间;技能2造成的伤害,以及冷却时间,怪兽的血量还有怪兽的防御力,每次你对怪兽的攻击伤害为技能1-防御力,或者技能2-防御力,或者技能1+技能2-防御力。最后问你打死这只怪兽最少需要多少时间。
(2)解题思路
1.考虑单独A怪兽一下,你能造成技能1-防御力,或者技能2-防御力
2.考虑前j - 1下用技能1A怪兽,第j下一起A怪兽。
3.考虑前j - 1下用技能2A怪兽,第j下一起A怪兽。
把这三个状态转移方程写出来,这个题就做完了。
(3)代码实现
#include "bits/stdc++.h"
using namespace std;
using ll = long long;
const int N = 5010;
ll dp[N];
void solve()
{
memset(dp,0x3f,sizeof(dp));
ll p1,t1,p2,t2,h,s;
cin >> p1 >> t1 >> p2 >> t2 >> h >> s;
dp[0] = 0;
for(int i = 1;i <= h;i++) {
dp[i] = min(dp[max(0LL,i - (p1 - s))] + t1,dp[max(0LL,i - (p2 - s))] + t2);
for(int j = 1;j <= i;j++) {
if(j * t1 >= t2) {
ll attack = (j - 1) * (p1 - s) + (j * t1 - t2) / t2 * (p2 - s) + (p1 + p2 - s);
dp[i] = min(dp[i],dp[max(0LL,i - attack)] + j * t1);
}
if(j * t2 >= t1) {
ll attack = (j - 1) * (p2 - s) + (j * t2 - t1) / t1 * (p1 - s) + (p1 + p2 - s);
dp[i] = min(dp[i],dp[max(0LL,i - attack)] + j * t2);
}
}
}
cout << dp[h] << endl;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
int T;
T = 1;
while(T --) {
solve();
}
return 0;
}
(1)题目大意
给你一个[l,r]的区间,每一次给每一个位数+1,现在问你会改变多少位。
(2)解题思路
对于每一位不是9的来说,会产生1的贡献,若为9则会产生2的贡献。我们计算这一位对高位产生了多少贡献即可,最后每一步加上来即可。
(3)代码实现
#include "bits/stdc++.h"
#define rep(i,z,n) for(int i = z;i <= n; i++)
#define per(i,n,z) for(int i = n;i >= z; i--)
#define ll long long
#define db double
#define PII pair<int,int>
#define fi first
#define se second
#define vi vector<int>
#define yes cout << "YES" << endl;
#define no cout << "NO" << endl;
using namespace std;
const int N = 1e5 + 10;
void solve()
{
int l,r;
cin >> l >> r;
int ans = 0,step;
string s1 = to_string(l),s2 = to_string(r);
s1 = string(s2.size() - s1.size(),'0') + s1;
step = r - l;
for(int i = s1.size() - 1;i >= 0;i--) {
ans += step;
step = (step + s1[i] - '0') / 10;
}
cout << ans << endl;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
int T = 1;
cin >> T;
while(T --) solve();
return 0;
}
(1)题目大意
给你n次操作,一个m,问你m最后能变成多少位。
(2)解题思路
很明显我们可以预处理出操作0-9i次会变成多少位,然后加上就可以了。
对于操作次数i + 数位j<10,那么dp[i][j] = 1;
否则dp[i][j] = dp[i - (10 - j)][0] + dp[i - (10 - j)][1];//就是在第i-(10-j)这次我们一个1加上一个0转移过来的。
(3)代码实现
#include "bits/stdc++.h"
#define rep(i,z,n) for(int i = z;i <= n; i++)
#define per(i,n,z) for(int i = n;i >= z; i--)
#define ll long long
#define db double
#define PII pair<int,int>
#define fi first
#define se second
#define vi vector<int>
#define yes cout << "YES" << endl;
#define no cout << "NO" << endl;
using namespace std;
const int N = 2e5 + 10,mod = 1e9 + 7;
int dp[N][10];
void init()
{
for(int i = 0;i <= 200000;i++)
for(int j = 0;j <= 9;j++)
if(j + i >= 10) dp[i][j] = (dp[i - (10 - j)][0] + dp[i - (10 - j)][1]) % mod;
else dp[i][j] = 1;
}
void solve()
{
int n,m;
cin >> n >> m;
int ans = 0;
while(n) {
ans = (ans + dp[m][n % 10]) % mod;
n /= 10;
}
cout << ans << endl;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
init();
int T = 1;
cin >> T;
while(T --) solve();
return 0;
}