梦月场(出题人是dreamoon 台湾人)
所以题解都是繁体字还有聊天记录hhh
感觉都是数学题啊QAQ
题解链接: https://pan.baidu.com/s/1bJb8UPlgkahMTxpkdpyOPw 提取码: 6j4x 复制这段内容后打开百度网盘手机App,操作更方便哦
06 string matching
HDU 6629 扩展KMP
Alone做的
是模板题 记得用long long
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int maxn=1e6+5;
char s[maxn];
long long ne[maxn];
void pre_EKMP(char x[],long long m,long long next[])
{
next[0]=m;
long long j=0;
while(j+1<m&&x[j]==x[j+1]) j++;
next[1]=j;
long long k=1;
for(long long i=2;i<m;i++)
{
long long p=next[k]+k-1;
long long L=next[i-k];
if(i+L<p+1) next[i]=L;
else
{
j=max((long long)0,p-i+1);
while(i+j<m&&x[i+j]==x[j]) j++;
next[i]=j;
k=i;
}
}
}
int main()
{
//freopen("in.txt","r",stdin);
int t;
scanf("%d",&t);
while(t--)
{
scanf("%s",s);
long long len=strlen(s);
pre_EKMP(s,len,ne);
long long sum=0;
for(long long i=1;i<len;i++)
{
if(ne[i]==0)
sum++;
else
{
sum+=ne[i];
if(ne[i]+i<len)
sum++;
}
}
//printf("\n");
printf("%lld\n",sum);
}
return 0;
}
07 permutation 2
HDU 6630 推公式
证明
感谢桑老师借我平板写过程orz
(平板真好玩)
AC代码如下:
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <iostream>
#include <cstring>
#include <queue>
#include <vector>
#include <bits/stdc++.h>
#define ll long long
using namespace std;
ll mod = 998244353;
ll a[200005];
int main()
{
a[0] = 0;
a[1] = 1;
a[2] = 1;
a[3] = 1;
a[4] = 2;
a[5] = 3;
a[6] = 4;
a[7] = 6;
a[8] = 9;
for (int i = 8; i < 200005; i++) {
a[i] = (a[i - 3] % mod + a[i - 1] % mod ) % mod;
}
int t, n, x, y;
ll L, R;
scanf("%d", &t);
// printf("%lld\n", a[50629]);
while (t--) {
scanf("%d%d%d", &n, &x, &y);
if (x == 1) {
L = 1;
} else {
L = x + 1;
}
if (y == n) {
R = n;
} else {
R = y - 1;
}
printf("%lld\n", a[R - L + 1]);
}
return 0;
}
04 equation
HDU 6627 数学题
题目大意:给出下列式子的,
求 x 的所有解
如果无解输出 0,有无穷解就输出 -1
其他情况就是输出解的个数以及解的分数形式(0 输出 0/1)
解决方法:先将所有的ai系数相加,所有的bi的系数相加
x1,x2,x3,……xm从小到大排序 (a1*x1+b1=0时成立)
得到 n+1 个区间
枚举所有区间的解 判断该解是否在区间内,存到数组中记录
#include <stdio.h>
#include <iostream>
#include <bits/stdc++.h>
using namespace std;
struct node {
int a, b;
double x;
int id;
} mm[100050], ans[100050];
queue<node>q;
int A[100050], B[100050];
int sum_a = 0, sum_b = 0, n, c, f, num;
double l, r;
int gcd(int a,int b)
{
return b? gcd(b,a%b):a;
}
bool cmp(node xx, node yy)
{
if (xx.x != yy.x) {
return xx.x < yy.x;
} else {
return xx.id < yy.id;
}
}
void run()
{
if (sum_a == 0 && sum_b == c) {
f = 1;
return ;
}
double aa;
aa = (double)(c - sum_b)/sum_a;
if (aa > l && aa <= r) {
int as = 1;
if (aa < 0) {
as = -1;
}
int xx = abs(c - sum_b), yy = abs(sum_a);
int zz = 0;
if (xx == 0) {
zz = yy;
} else {
zz = gcd(xx, yy);//自带gcd,尽量少用
}
// node k ;
// k.a = xx / zz * as;
// k.b = yy / zz;
// q.push(k);
ans[num].a = xx / zz * as;
ans[num].b = yy / zz;
num++;
}
return;
}
int main()
{
int t;
scanf("%d", &t);
while (t--) {
// while (!q.empty()) {
// q.pop();
// }
memset(A, 0, sizeof A);
memset(B, 0, sizeof B);
f = 0;
sum_a = 0, sum_b = 0;
scanf("%d%d", &n, &c);
for (int i = 0; i < n; i++) {
scanf("%d%d", &A[i], &B[i]);
mm[i].a = A[i];
mm[i].b = B[i];
mm[i].id = i;
mm[i].x = (double)B[i] / A[i] * (-1.0);
sum_a -= A[i];
sum_b -= B[i];
}
sort(mm, mm + n, cmp);
num = 0;
l = -1e15, r = -1e15;
mm[n].x = 1e15;
for (int i = 0; i <= n; i++) {
l = r, r = mm[i].x;
if (f != 1) {
run();
}
sum_a += mm[i].a * 2;
sum_b += mm[i].b * 2;
}
if (f == 1) {
printf("-1\n");
} else {
// printf("%d",q.size());
printf("%d", num);
for (int i = 0; i < num; i++) {
// for (int i = 0; i < q.size(); i++) {
// while (!q.empty()) {
// node k = q.front();
// q.pop();
// printf(" %d/%d", k.a, k.b);
printf(" %d/%d", ans[i].a, ans[i].b);
// }
}
printf("\n");
}
}
return 0;
}
05 permutation 1
HDU 6628 全排列
关于全排列函数 next_permutation() 的使用 参考:https://blog.youkuaiyun.com/AC_Gibson/article/details/45308645
题目大意:询问 T 次,求出1~ N 的全排列中以相邻元素之差字典序从小到大排序的第 K 个序列。