题解
题目求解 (a,b) 出口,反向思维,由 (a,b) 往 (x,y) 推导,发现仅有一条可行路径,如果不存在就输出 −1 即可
代码
#include
#include
#include
#include
#include
#include
#include
#define FIN freopen("input.txt", "r", stdin)
#define FOUT freopen("output.txt", "w", stdout)
using namespace std;
typedef long long LL;
const int MAXN = 4e5 + 5;
const int INF = 0x3f3f3f3f;
bool flag;
int x, y;
void gcd(int a, int b) {
while(a != 0 && b != 0) {
if(a == x && b == y || b == x && a == y) {
flag = true;
break;
}
if(a > b) {
int t = a / b;
if(t > 2){
a = a - b * (t - 2);
}
a = a - b;
} else {
int t = b / a;
if(t > 2){
b = b - a * (t - 2);
}
b = b - a;
}
}
}
int a, b;
int main() {
int _, a, b;
scanf("%d", &_);
while(_ --) {
scanf("%d%d%d%d", &x, &y, &a, &b);
flag = false;
gcd(a, b);
puts(flag ? "YES" : "NO");
}
return 0;
}
题解
由题目可以知道,总共存在最多 1000 个不同的数,然后是无序的,接着就可以列出如下状态转移方程:
map
来维护数字和出现的个数,并且保证它有序,那么
k 的变化就不会超过
2 次,然后直接递推过去就可以得到答案了。
代码
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define FIN freopen("input.txt", "r", stdin)
#define FOUT freopen("output.txt", "w", stdout)
using namespace std;
typedef long long LL;
const int MAXN = 1e3 + 5;
const int INF = 0x3f3f3f3f;
int N, M;
int A[MAXN];
int dp[MAXN][MAXN];
map<int, int> Mii;
vectorint , int> > vpii;
int main() {
while(~scanf("%d%d", &N, &M)) {
Mii.clear();
for(int i = 1; i <= N; i ++) {
scanf("%d", &A[i]);
Mii[A[i]] ++;
}
memset(dp, 0, sizeof(dp));
vpii.clear();
vpii.push_back(make_pair(-10, 0));
for(map<int, int>::iterator it = Mii.begin(); it != Mii.end(); it ++) {
vpii.push_back(make_pair(it -> first, it -> second));
}
for(int i = 1; i < vpii.size() ; i ++) {
for(int k = 1; k <= M; k ++) {
for(int j = i - 1; j >= 0; j --) {
dp[i][k] = max(dp[i][k], dp[i - 1][k]);
if(vpii[i].first - vpii[j].first > 1) {
dp[i][k] = max(dp[i - 1][k], dp[j][k - 1] + vpii[i].first * vpii[i].second);
break;
}
}
//printf("%d, %d : [%d]\n", i, k, dp[i][k]);
}
}
printf("%d\n", dp[vpii.size() - 1][M]);
}
return 0;
}
题解
跟求不同回文子串的数目有点类似,不过这次不能统计相同的,所以我们同样用马拉车处理出回文子串的数目,然后用后缀数组处理出相邻的后缀的最长公共前缀,很明显拥有相同前缀的子串是会重复的,所以用一个临时变量维护已经计算过的子串长度,然后后面加的时候减去它就可以得到正确结果,个人用的模板是挑战程序设计竞赛上的后缀数组,因为非常好理解。
代码
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define FIN freopen("input.txt", "r", stdin)
#define FOUT freopen("output.txt", "w", stdout)
using namespace std;
typedef long long LL;
const int MAXN = 8e5 + 5;
const int INF = 0x3f3f3f3f;
char S[MAXN], tS[MAXN << 1];
int len[MAXN << 1], sz;
int rank_[MAXN << 1], tmp[MAXN << 1], lcp[MAXN << 1], sa[MAXN << 1];
int g_k;
void mlc(){
sz = 0;
int ln = strlen(S);
tS[sz ++] = '$';
for(int i = 0;i < ln;i ++){
tS[sz ++] = '#';
tS[sz ++] = S[i];
}
tS[sz ++] = '#';
tS[sz] = '@';
int mx = 0, id = 0;
len[0] = 1;
for(int i = 1;i < sz;i ++){
if(mx > i){
len[i] = min(len[2 * id - i], mx - i);
}
else{
len[i] = 1;
}
while(tS[i + len[i]] == tS[i - len[i]]) len[i] ++;
if(len[i] + i > mx){
mx = len[i] + i;
id = i;
}
}
}
bool compare_sa(int i, int j){
if(rank_[i] != rank_[j]) return rank_[i] < rank_[j];
else {
int ri = i + g_k <= sz ? rank_[i + g_k] : -1;
int rj = j + g_k <= sz ? rank_[j + g_k] : -1;
return ri < rj;
}
}
void construct_sa(){
for(int i = 0;i <= sz;i ++){
sa[i] = i;
rank_[i] = i < sz ? tS[i] : -1;
}
for(g_k = 1;g_k <= sz;g_k <<= 1){
sort(sa, sa + sz + 1, compare_sa);
tmp[sa[0]] = 0;
for(int i = 1;i <= sz;i ++){
tmp[sa[i]] = tmp[sa[i - 1]] + (compare_sa(sa[i - 1], sa[i]) ? 1 : 0);
}
for(int i = 0;i <= sz;i ++){
rank_[i] = tmp[i];
}
}
}
void construct_lcp(){
for(int i = 0;i <= sz;i ++) rank_[sa[i]] = i;
int h = 0;
lcp[0] = 0;
for(int i = 0;i < sz;i ++){
int j = sa[rank_[i] - 1];
if(h > 0) h --;
for(;j + h < sz && i + h < sz;h ++){
if(tS[j + h] != tS[i + h]) break;
}
lcp[rank_[i] - 1] = h;
}
}
void solve(){
mlc();
construct_sa();
construct_lcp();
int t = 0, ans = 0;
for(int i = 1;i <= sz;i ++){
int f = sa[i];
t = min(t, lcp[i - 1]);
if(len[f] <= t) continue;
ans += (len[f] - t) / 2;
t = len[f];
}
printf("%d\n", ans);
}
int main(){
while(~scanf("%s", S)){
memset(len , 0, sizeof(len));
memset(rank_, 0, sizeof(len));
memset(tmp, 0, sizeof(tmp));
memset(lcp, 0, sizeof(lcp));
memset(sa, 0, sizeof(sa));
solve();
}
}