agc031
作者:互联网
T1 题意:给你一个串,求所有子序列个数,满足没有相同字符。1e5,2s。
解:考虑一个合法的子序列。其中每个字母的出现位置都有(出现次数)种选择。还可以不选,要 + 1。
然后乘起来就做完了。如果变成子串的话更简单,每个位置为开头的长度不会超过26,直接暴力。本质不同子串就开个hash池判重。
本质不同子序列......不会。
1 #include <bits/stdc++.h> 2 3 const int N = 100010, MO = 1e9 + 7; 4 5 char str[N]; 6 int bin[26]; 7 8 int main() { 9 int n; 10 scanf("%d", &n); 11 scanf("%s", str); 12 for(int i = 0; i < n; i++) { 13 bin[str[i] - 'a']++; 14 } 15 int ans = 1; 16 for(int i = 0; i < 26; i++) { 17 ans = 1ll * ans * (bin[i] + 1) % MO; 18 } 19 printf("%d", (ans + MO - 1) % MO); 20 21 return 0; 22 }AC代码
T2 题意:给你一个序列,可以若干次选择两个相同的数字,使其之间的数字全部变成这个数字。求最终可能的序列总数。2e5,2s。
解:发现选出来的序列一定是一些相离的,所以可以DP,设f[i]表示前i位可能的方案总数。那么第i位可能和前面任一个相同的数匹配,f[i] += f[j - 1]。
同时也可能不匹配,相当于自己跟自己匹配。我们要对所有ai等于一个数的DP值求和,直接开个桶。
发现有连续相同的数的时候会挂,把它们缩起来。
1 #include <bits/stdc++.h> 2 3 typedef long long LL; 4 const int N = 200010, MO = 1e9 + 7; 5 6 int a[N], bin[N], f[N]; 7 8 int main() { 9 10 int n; 11 scanf("%d", &n); 12 for(int i = 1; i <= n; i++) { 13 scanf("%d", &a[i]); 14 if(a[i] == a[i - 1]) { 15 i--; 16 n--; 17 } 18 } 19 f[0] = 1; 20 for(int i = 1; i <= n; i++) { 21 (bin[a[i]] += f[i - 1]) %= MO; 22 f[i] = bin[a[i]]; 23 } 24 printf("%d", f[n]); 25 26 return 0; 27 }AC代码
标签:bin,26,int,MO,ans,序列,agc031 来源: https://www.cnblogs.com/huyufeifei/p/10681333.html