クレイジーモードでは、私がこれまでの進歩に追いつくまで、おそらく...何回か続く、問題の水溶液オンになっています。
以下の説明は、次のとおりです。
\ [1001【HDU-6624】【1004 \\ HDU-6627】【1005 \\ HDU-6628】【1006 \\ HDU-6629】【1007 \\ HDU-6630 [\]
[1001]数学のHDU-6624分数
http://acm.hdu.edu.cn/showproblem.php?pid=6624
検索最小の正の整数\(B \)を満足\(<B \)と\(A = BX(MOD \ P)\) 。
参考:https://blog.csdn.net/Sarah_Wang0220/article/details/98771865
実測値:\(0 <A <B \)、\ (A BX = Pyと+ \) ==> \(0 <= BX-PyとA <B \) ==> \(\ FRAC {X} {P} <\ FRAC {B}、{Y} <\ FRAC {P} 1-X} {\)、最小必要\(Bを\)。
反復法:
\ [\整列\ため\ X FRAC {P} {} <\ FRAC {B}、{Y} <\ FRAC {} {P} 1-X \と\ P> X \\&&} {始まります\従って\ FRAC {P} { X}> 0 \ \ 取る\ T = \ FRAC {P} {X} \\&\従って\ FRAC {P-TX} {X} <\ FRAC {B-TY} { Y} <\ FRAC {PT( X-1)}、{X-1} \\& 逆数を取って得られた:\のFRAC {X-1} {PT(X-1)} <\ FRAC {Y} {B-TY } <\ FRAC {X} { P-TX} \\& 同様に、左側の整数部分を減算することにより継続\\&ケースの\ B「= B - TY減少\端{整列} \]
#include <map>
#include <set>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <stack>
#include <queue>
#include <bitset>
#include <cctype>
#include <cstdio>
#include <vector>
#include <string>
#include <cstdlib>
#include <cstring>
#include <fstream>
#include <iomanip>
#include <numeric>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const double PI = acos(-1.0);
const double eps = 1e-6;
const int inf = 0x3f3f3f3f;
const int mod = 1e9 + 7;
void solve(ll a, ll b, ll &c, ll &d, ll e, ll f) {
ll t = a/b;
if(e/f > t) {
c = t+1;
d = 1;
return ;
}
a = a - t*b;
e = e - t*f;
solve(f, e, d, c, b, a);
c = c + t*d;
}
int main() {
int t;
scanf("%d", &t);
while(t--) {
ll p, x;
scanf("%lld%lld", &p, &x);
ll b, y;
solve(p, x, b, y, p, x-1);
printf("%lld/%lld\n", b*x-p*y, b);
}
return 0;
}
[1004]数学のHDU-6627式
http://acm.hdu.edu.cn/showproblem.php?pid=6627
所与\(N- \)と\(C \) 、入力\(N- \)\(a_iを\)と\(B_i \)は、全てに対して計算される\(X \)ようにソリューション:\(\ SUM ^ { {I} _ = N-1} | + B_i a_ix | = C \)。
見つけるために方程式の絶対値の各々について\(X \)範囲を、次に列挙範囲、統計的ソリューションの数を並べ替えます。
#include <map>
#include <set>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <stack>
#include <queue>
#include <bitset>
#include <cctype>
#include <cstdio>
#include <vector>
#include <string>
#include <cstdlib>
#include <cstring>
#include <fstream>
#include <iomanip>
#include <numeric>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const double PI = acos(-1.0);
const double eps = 1e-6;
const int inf = 0x3f3f3f3f;
const int mod = 1e9 + 7;
const int maxn = 1e5+5;
int n;
ll c;
ll suma[maxn], sumb[maxn]; // 记录 系数/常数 前缀和
map<double, int> vis;
struct node {
ll a, b;
double f;
bool operator < (const node &q) const {
return f > q.f;
}
}p[maxn], ans[maxn];
bool cmp(node x, node y) {
return x.f < y.f;
}
int main() {
int t;
scanf("%d", &t);
suma[0] = sumb[0] = 0;
while(t--) {
vis.clear();
scanf("%d%lld", &n, &c);
for(int i = 1; i <= n; i++) {
scanf("%lld%lld", &p[i].a, &p[i].b);
p[i].f = -1.0*p[i].b/p[i].a; // 每组方程等于 0的解
}
sort(p+1, p+1+n);
for(int i = 1; i <= n; i++) {
suma[i] = suma[i-1] + p[i].a;
sumb[i] = sumb[i-1] + p[i].b;
}
int flag = 0;
int cnt = 0;
for(int i = 0; i <= n; i++) {
ll A = suma[n] - 2*suma[i]; // 当前区间解的 系数 前缀和(分母)
ll B = sumb[n] - 2*sumb[i]; // 当前区间解的 常数 前缀和
ll C = c - B; // 等式常数移到右边获取最终常数(分子)
if(A == 0) {
if(C == 0) { // 无穷解
flag = 1;
break;
}
else { // 无解
continue;
}
}
else {
ll temp = __gcd(abs(C), abs(A));
double mark = 1.0 * C / A;
if(vis[mark] == 0) { // 去重
if((i==n || mark>p[i+1].f) && (i==0 || mark<=p[i].f)) { // 边界判定
ans[cnt].a = C / temp;
ans[cnt].b = A / temp;
ans[cnt++].f = mark;
}
}
}
}
if(flag == 1) {
printf("-1\n");
}
else {
printf("%d", cnt);
sort(ans, ans+cnt, cmp);
for(int i = 0; i < cnt; i++) {
if(ans[i].a*ans[i].b > 0) {
printf(" %lld/%lld", abs(ans[i].a), abs(ans[i].b));
}
else if(ans[i].a*ans[i].b == 0) {
printf(" 0/1");
}
else {
printf(" -%lld/%lld", abs(ans[i].a), abs(ans[i].b));
}
}
printf("\n");
}
}
return 0;
}
HDU-6628順列1を考える[1005]
http://acm.hdu.edu.cn/showproblem.php?pid=6628
\(T \)場合により、既知の配列は:\(p_1p_2 ... P_N \) 、配列の差として定義される:\(P_1、P_2、P_3-P_2、...、N - P_N-P_ {} 1 \) 。与えられた\(N \)と\(k個\)は、シーケンス見つける\(1,2,3、...、nは\ ) には、出力、Kにランクシーケンスのわずかな差で。(\ (2 \ n型のLeq \のLeq 20は\ \ \である。1 \のLeq K \のLeqの分(10 ^ 4、N-!)\) )
以下のための\(n個\ \当量8) 、ライン上で直接暴力。
以下のために\(n>は8 \)時間、法律を見つける:下に置くために(N \)\をこの数は、後者が最小である\(、2、3、...、nは- 1 \) 、そして後にのみ8ビットとして、配置することができる\(8!> 10 ^ 4 \) 。
#include <map>
#include <set>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <stack>
#include <queue>
#include <bitset>
#include <cctype>
#include <cstdio>
#include <vector>
#include <string>
#include <cstdlib>
#include <cstring>
#include <fstream>
#include <iomanip>
#include <numeric>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const double PI = acos(-1.0);
const double eps = 1e-6;
const int inf = 0x3f3f3f3f;
const int mod = 1e9 + 7;
const int maxn = 4e4+500;
int a[10] = {1, 2, 3, 4, 5, 6, 7, 8};
int a_8[10] = {1, 2, 3, 4, 5, 6, 7};
int _a_8[10] = {1, 2, 3, 4, 5, 6, 8};
int tot, tot1, tot2, cnt;
struct node {
int z[10];
bool operator < (const node x) const {
for(int i = 0; i < 8; i++) {
if(z[i] < x.z[i]) {
return 1;
}
else if(z[i] == x.z[i]) {
continue;
}
else {
return 0;
}
}
}
}temp[maxn], t_8[maxn], _t_8[maxn];
struct NODE {
int z[10];
int x[10];
}res[maxn];
bool cmp(NODE nn, NODE mm) {
for(int i = 0; i < 8; i++) {
if(nn.x[i] < mm.x[i]) {
return 1;
}
else if(nn.x[i] == mm.x[i]) {
continue;
}
else {
return 0;
}
}
return 0;
}
void init() {
do {
for(int i = 0; i < 8; i++) {
temp[tot].z[i] = a[i];
}
tot++;
} while(next_permutation(a, a+8));
sort(temp, temp+tot);
}
void cal(int n) {
int aa[10];
for(int i = 0; i < n; i++) {
aa[i] = i+1;
}
do {
for(int i = 0; i < n; i++) {
res[cnt].z[i] = aa[i];
}
for(int i = 1; i < n; i++) {
res[cnt].x[i-1] = res[cnt].z[i] - res[cnt].z[i-1];
// cout << res[cnt].x[i-1] << " ";
}
// cout << endl;
cnt++;
} while(next_permutation(aa, aa+n));
sort(res, res+cnt, cmp);
}
int main() {
tot = tot1 = tot2 = 0;
init();
int t;
scanf("%d", &t);
while(t--) {
int n, k;
scanf("%d%d", &n, &k);
if(n <= 8) {
cnt = 0;
cal(n);
for(int i = 0; i < n; i++) {
printf("%d%c", res[k-1].z[i], i==n-1?'\n':' ');
}
}
else {
printf("%d ", n);
for(int i = 1; i < n-8; i++) {
printf("%d ", i);
}
k = k - 1;
for(int i = 0; i < 8; i++) {
printf("%d%c", temp[k].z[i]+n-9, i==7?'\n':' ');
}
}
}
return 0;
}
【1006】拡張KMP HDU-6629文字列マッチング
http://acm.hdu.edu.cn/showproblem.php?pid=6629
文字列を考えると、今では共通のプレフィックスのそれぞれを持っているし、元の文字列をサフィックス、どのくらいの暴力に必要なプロセス工程の実施を依頼する必要があります。
KMP裸のタイトルを拡張。
#include <map>
#include <set>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <stack>
#include <queue>
#include <bitset>
#include <cctype>
#include <cstdio>
#include <vector>
#include <string>
#include <cstdlib>
#include <cstring>
#include <fstream>
#include <iomanip>
#include <numeric>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const double PI = acos(-1.0);
const double eps = 1e-6;
const int inf = 0x3f3f3f3f;
const int mod = 1e9 + 7;
const int maxn = 1e6+5;
char s[maxn];
char T[maxn];
ll nxt[maxn], extend[maxn];
void getnxt(char str[]) {
int i = 0, j, po;
int len = strlen(str);
nxt[0] = len;
while(str[i] == str[i+1] && i+1 < len) i++;
nxt[1] = i;
po = 1;
for(i = 2; i < len; i++) {
if(nxt[i-po]+i < nxt[po]+po) // case1 可以直接得到next[i]的值
nxt[i] = nxt[i-po];
else { // case2 要继续匹配才能得到next[i]的值
j = nxt[po] + po - i;
if(j < 0) // 如果i>po+next[po],则要从头开始匹配
j = 0;
while(str[j] == str[j+i] && i+j < len) j++;
nxt[i] = j;
po = i;
}
}
}
void EXKMP(char s1[], char s2[]) {
int i = 0, j, po;
int l1 = strlen(s1);
int l2 = strlen(s2);
getnxt(s2);
while(s1[i] == s2[i] && i < l2 && i < l1) i++;
extend[0] = i;
po = 0;
for(i = 1; i < l1; i++) {
if(nxt[i-po]+i < extend[po]+po) //case1 直接可以得到extend[i]的值
extend[i] = nxt[i-po];
else { // case2 要继续匹配才能得到extend[i]的值
j = extend[po]+po-i;
if(j < 0) // 如果i>extend[po]+po则要从头开始匹配
j = 0;
while(s1[j+i]==s2[j] && i+j < l1 && j < l2) j++;
extend[i] = j;
po = i;
}
}
}
int main() {
int t;
scanf("%d", &t);
while(t--) {
scanf("%s", s);
strcpy(T, s);
EXKMP(s, T);
int n = strlen(s);
ll ans = 0;
for(int i = 1; i < n; i++) {
ans = ans + extend[i];
if(extend[i] != n-i) {
ans = ans + 1;
}
}
printf("%lld\n", ans);
}
return 0;
}
[1007]法律HDU-6630順列2
http://acm.hdu.edu.cn/showproblem.php?pid=6630
与えられた\(N-、X、Y \)のために、\(1 \)に\(N- \)この\(N- \)番号、満足:\(P_1 = X、\ = Y P_2、\ | p_i- {I} 1-P_ |。\のLeq 2 \(1 \のLeq I <N-)\)。
法律ができ見つけるためにテーブルをヒット。
#include <map>
#include <set>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <stack>
#include <queue>
#include <bitset>
#include <cctype>
#include <cstdio>
#include <vector>
#include <string>
#include <cstdlib>
#include <cstring>
#include <fstream>
#include <iomanip>
#include <numeric>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const double PI = acos(-1.0);
const double eps = 1e-6;
const int inf = 0x3f3f3f3f;
const int mod = 998244353;
const int maxn = 1e5+5;
ll a[maxn];
int main() {
int t;
scanf("%d", &t);
while(t--) {
int n, x, y;
scanf("%d%d%d", &n, &x, &y);
if(n == 2 || n == 3) {
printf("1\n");
continue;
}
a[0] = 0;
if(x == 1) {
a[1] = 1;
a[2] = 1;
for(int i = 3; i <= y-x; i++) {
if(i == n-x) {
a[i] = (a[i-1] + a[i-2] + a[i-3]) % mod;
}
else {
a[i] = (a[i-1] + a[i-3]) % mod;
}
}
}
else if(x == n-1) {
printf("1\n");
continue;
}
else {
a[1] = 0;
a[2] = 1;
for(int i = 3; i <= y-x; i++) {
if(i == n-x) {
a[i] = (a[i-1] + a[i-2] + a[i-3]) % mod;
}
else {
a[i] = (a[i-1] + a[i-3]) % mod;
}
}
}
printf("%lld\n", a[y-x]);
}
return 0;
}