比赛结束后才做的,发现DIV2的题目对算法要求不高,但对思路的扩展有帮助。
A. Flipping Game
可以转化成最大子段和模型,然后求出起始下标和结束下标再搞一下就可以了
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <queue>
#include <algorithm>
#include <vector>
#include <cstring>
#include <stack>
#include <cctype>
#include <utility>
#include <map>
#include <string>
#include <climits>
#include <set>
#include <string>
#include <sstream>
#include <utility>
#include <ctime>
using std::priority_queue;
using std::vector;
using std::swap;
using std::stack;
using std::sort;
using std::max;
using std::min;
using std::pair;
using std::map;
using std::string;
using std::cin;
using std::cout;
using std::set;
using std::queue;
using std::string;
using std::istringstream;
using std::make_pair;
using std::getline;
using std::greater;
using std::endl;
using std::multimap;
using std::deque;
typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int, int> PAIR;
typedef multimap<int, int> MMAP;
const int MAXN(200010);
const int MAXM(10010);
const int MAXE(10010);
const int MAXH(19);
const int INFI(2000000000);
const int MOD(10000);
const ULL BASE(31);
const LL LIM(10000000);
const int INV(-10000);
int arr[110];
int lind, rind, mx;
int main()
{
int n;
while(~scanf("%d", &n))
{
for(int i = 1; i <= n; ++i)
{
scanf("%d", arr+i);
arr[i] = arr[i]? -1: 1;
}
mx = arr[1];
lind = rind = 1;
int tsum = 0, ts;
for(int i = 1; i <= n; ++i)
{
if(tsum > 0)
tsum += arr[i];
else
{
tsum = arr[i];
ts = i;
}
if(tsum > mx)
{
mx = tsum;
lind = ts;
rind = i;
}
}
int ans = 0;
for(int i = lind; i <= rind; ++i)
if(arr[i] == 1)
++ans;
for(int i = 1; i < lind; ++i)
if(arr[i] == -1)
++ans;
for(int i = rind+1; i <= n; ++i)
if(arr[i] == -1)
++ans;
printf("%d\n", ans);
}
return 0;
}
有多种解法,我直接打了素数表输出了
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <queue>
#include <algorithm>
#include <vector>
#include <cstring>
#include <stack>
#include <cctype>
#include <utility>
#include <map>
#include <string>
#include <climits>
#include <set>
#include <string>
#include <sstream>
#include <utility>
#include <ctime>
using std::priority_queue;
using std::vector;
using std::swap;
using std::stack;
using std::sort;
using std::max;
using std::min;
using std::pair;
using std::map;
using std::string;
using std::cin;
using std::cout;
using std::set;
using std::queue;
using std::string;
using std::istringstream;
using std::make_pair;
using std::getline;
using std::greater;
using std::endl;
using std::multimap;
using std::deque;
typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int, int> PAIR;
typedef multimap<int, int> MMAP;
const int MAXN(200010);
const int MAXM(10010);
const int MAXE(10010);
const int MAXH(19);
const int INFI(2000000000);
const int MOD(10000);
const ULL BASE(31);
const LL LIM(10000000);
const int INV(-10000);
bool is_prime[2000001];
int prim[200010];
int count = 0;
void init()
{
memset(is_prime, -1, sizeof(is_prime));
for(int i = 2; i <= 2000000; ++i)
if(is_prime[i])
{
prim[count++] = i;
for(LL j = (LL)i*i; j <= 2000000; j += i)
is_prime[j] = false;
}
};
int main()
{
init();
int n;
while(~scanf("%d", &n))
{
for(int i = 0; i < n; ++i)
{
if(i)
printf(" ");
printf("%d", prim[i]);
}
printf("\n");
}
return 0;
}
C. Magic Five
题解给了一种解法,我想的是用矩阵快速幂搞的,毕竟k的范围太像矩阵题的数据范围了
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <queue>
#include <algorithm>
#include <vector>
#include <cstring>
#include <stack>
#include <cctype>
#include <utility>
#include <map>
#include <string>
#include <climits>
#include <set>
#include <string>
#include <sstream>
#include <utility>
#include <ctime>
using std::priority_queue;
using std::vector;
using std::swap;
using std::stack;
using std::sort;
using std::max;
using std::min;
using std::pair;
using std::map;
using std::string;
using std::cin;
using std::cout;
using std::set;
using std::queue;
using std::string;
using std::istringstream;
using std::make_pair;
using std::getline;
using std::greater;
using std::endl;
using std::multimap;
using std::deque;
typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int, int> PAIR;
typedef multimap<int, int> MMAP;
const int MAXN(200010);
const int MAXM(10010);
const int MAXE(10010);
const int MAXH(19);
const int INFI(2000000000);
const int MOD(1000000007);
const ULL BASE(31);
const LL LIM(10000000);
const int INV(-10000);
LL table[100010];
struct MAT
{
int r, c;
LL arr[2][2];
MAT(int tr, int tc): r(tr), c(tc)
{
memset(arr, 0, sizeof(arr[0])*r);
}
MAT()
{}
void reset()
{
memset(arr, 0, sizeof(arr[0])*r);
}
void identity()
{
reset();
for(int i = 0; i < r; ++i)
arr[i][i] = 1;
}
};
void mat_mul(const MAT &op1, const MAT &op2, MAT &re)
{
re.r = op1.r;
re.c = op2.c;
re.reset();
for(int i = 0; i < op1.c; ++i)
for(int j = 0; j < op1.r; ++j)
for(int k = 0; k < op2.c; ++k)
re.arr[j][k] = (re.arr[j][k]+op1.arr[j][i]*op2.arr[i][k])%MOD;
}
MAT t1, t2, *tp1, *tp2, *tre, *temp;
void mat_pow(const MAT &op, int n, MAT &re)
{
t1 = op;
re.r = op.r;
re.c = op.c;
re.identity();
tp1 = &t1;
tp2 = &t2;
tre = &re;
for(int i = 0; (1LL << i) <= n; ++i)
{
if(n&(1LL << i))
{
temp = tp2;
tp2 = tre;
tre = temp;
mat_mul(*tp1, *tp2, *tre);
}
mat_mul(*tp1, *tp1, *tp2);
temp = tp2;
tp2 = tp1;
tp1 = temp;
}
re = *tre;
}
MAT op1, op2, re;
char str[100010];
int main()
{
table[0] = 1;
for(int i = 1; i <= 100000; ++i)
table[i] = table[i-1]*2%MOD;
while(~scanf("%s", str))
{
LL ans = 0;
int len = strlen(str);
for(int i = 0; i < len; ++i)
if(str[i] == '0' || str[i] == '5')
ans = (ans+table[i])%MOD;
op1.r = op1.c = 2;
op1.arr[0][0] = table[len];
op1.arr[0][1] = 0;
op1.arr[1][0] = 1;
op1.arr[1][1] = 1;
int K;
scanf("%d", &K);
mat_pow(op1, K, re);
op2.r = 2;
op2.c = 1;
op2.arr[0][0] = 1;
op2.arr[1][0] = 0;
mat_mul(re, op2, op1);
ans = ans*op1.arr[1][0]%MOD;
printf("%I64d\n", ans);
}
return 0;
}
D. Block Tower
这题注意到不用求最小操作数就好搞了,每个4连通块只有一个Blue塔,剩下的都可以是Red塔
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <queue>
#include <algorithm>
#include <vector>
#include <cstring>
#include <stack>
#include <cctype>
#include <utility>
#include <map>
#include <string>
#include <climits>
#include <set>
#include <string>
#include <sstream>
#include <utility>
#include <ctime>
using std::priority_queue;
using std::vector;
using std::swap;
using std::stack;
using std::sort;
using std::max;
using std::min;
using std::pair;
using std::map;
using std::string;
using std::cin;
using std::cout;
using std::set;
using std::queue;
using std::string;
using std::istringstream;
using std::make_pair;
using std::getline;
using std::greater;
using std::endl;
using std::multimap;
using std::deque;
typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int, int> PAIR;
typedef multimap<int, int> MMAP;
const int MAXN(200010);
const int MAXM(10010);
const int MAXE(10010);
const int MAXH(19);
const int INFI(2000000000);
const int MOD(1000000007);
const ULL BASE(31);
const LL LIM(10000000);
const int INV(-10000);
int move_x[4] = {0, -1, 0, 1};
int move_y[4] = {-1, 0, 1, 0};
int op[750010][3];
char mp[510][510];
bool vis[510][510];
int count;
int N, M;
void dfs(int x, int y, bool flag)
{
vis[x][y] = true;
op[++count][0] = 0;
op[count][1] = x;
op[count][2] = y;
for(int i = 0; i < 4; ++i)
{
int tx = x+move_x[i], ty = y+move_y[i];
if(tx >= 1 && tx <= N && ty >= 1 && ty <= M && mp[tx][ty] == '.' && !vis[tx][ty])
dfs(tx, ty, true);
}
if(flag)
{
op[++count][0] = 1;
op[count][1] = x;
op[count][2] = y;
op[++count][0] = 2;
op[count][1] = x;
op[count][2] = y;
}
}
char print[3] = {'B', 'D', 'R'};
int main()
{
while(~scanf("%d%d", &N, &M))
{
for(int i = 1; i <= N; ++i)
scanf("%s", mp[i]+1);
for(int i = 1; i <= N; ++i)
for(int j = 1; j <= M; ++j)
vis[i][j] = false;
count = 0;
for(int i = 1; i <= N; ++i)
for(int j = 1; j <= M; ++j)
if(mp[i][j] == '.' && !vis[i][j])
dfs(i, j, false);
printf("%d\n", count);
for(int i = 1; i <= count; ++i)
printf("%c %d %d\n", print[op[i][0]], op[i][1], op[i][2]);
}
return 0;
}
E. Axis Walking
开始想到是O(2^n*n)的算法,复杂度太高了,不过没想到CF服务器性能这么好,这么高的复杂度都可以过,看来以后再CF上做题要自己卡一下时间了。
由于0<=k<=2题解上给的是中途相遇法和容斥原理相结合,估计比赛中没人会有这样的灵感吧
照着题解写了一份O(3^(n/2)*n^2*log(3^(n/2)))也就是O(3^(n/2)*n^3)复杂度的代码,纳尼竟然超时,这复杂比上面的可小多了啊,难道map就这么慢吗QAQ,邪恶的打补丁过了
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <queue>
#include <algorithm>
#include <vector>
#include <cstring>
#include <stack>
#include <cctype>
#include <utility>
#include <map>
#include <string>
#include <climits>
#include <set>
#include <string>
#include <sstream>
#include <utility>
#include <ctime>
using std::priority_queue;
using std::vector;
using std::swap;
using std::stack;
using std::sort;
using std::max;
using std::min;
using std::pair;
using std::map;
using std::string;
using std::cin;
using std::cout;
using std::set;
using std::queue;
using std::string;
using std::istringstream;
using std::make_pair;
using std::getline;
using std::greater;
using std::endl;
using std::multimap;
using std::deque;
typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int, int> PAIR;
typedef multimap<int, int> MMAP;
const int MAXN(200010);
const int MAXM(10010);
const int MAXE(10010);
const int MAXH(19);
const int INFI(2000000000);
const int MOD(1000000007);
const ULL BASE(31);
const LL LIM(10000000);
const int INV(-10000);
LL fact[25];
LL forbid1, forbid2;
LL ans;
int N, tn;
int arr[25];
struct ELE1
{
LL re;
int cnt;
ELE1(){}
ELE1(LL re_, int cnt_): re(re_), cnt(cnt_){}
friend bool operator < (const ELE1 &op1, const ELE1 &op2)
{
return op1.re == op2.re? op1.cnt < op2.cnt: op1.re < op2.re;
}
};
map<ELE1, int> mp1;
struct ELE2
{
LL re1, re2;
int cnt1, cnt2;
ELE2(){}
ELE2(LL re1_, int cnt1_, LL re2_, int cnt2_): re1(re1_), cnt1(cnt1_), re2(re2_), cnt2(cnt2_){}
friend bool operator < (const ELE2 &op1, const ELE2 &op2)
{
return op1.re1 == op2.re1? (op1.re2 == op2.re2? (op1.cnt1 == op2.cnt1? op1.cnt2 < op2.cnt2: op1.cnt1 < op2.cnt1): op1.re2 < op2.re2): op1.re1 < op2.re1;
}
};
map<ELE2, int> mp2;
void dfs1(int dep, LL re, int cnt)
{
if(re > forbid1)
return;
if(dep == N)
{
if(mp1.find(ELE1(re, cnt)) == mp1.end())
mp1.insert(make_pair(ELE1(re, cnt), 1));
else
++mp1[ELE1(re, cnt)];
return;
}
dfs1(dep+1, re, cnt);
dfs1(dep+1, re+arr[dep], cnt+1);
}
void dfsans1(int dep, LL re, int cnt)
{
if(re > forbid1)
return;
if(dep == tn)
{
int temp = N-tn;
for(int i = 0; i <= temp; ++i)
if(mp1.find(ELE1(forbid1-re, i)) != mp1.end())
ans = (fact[cnt+i]*fact[N-cnt-i]%MOD*mp1[ELE1(forbid1-re, i)]+ans)%MOD;
return;
}
dfsans1(dep+1, re, cnt);
dfsans1(dep+1, re+arr[dep], cnt+1);
}
void dfs2(int dep, LL re1, int cnt1, LL re2, int cnt2)
{
if(re1 > forbid1 || re1+re2 > forbid2)
return;
if(dep == N)
{
if(mp2.find(ELE2(re1, cnt1, re2, cnt2)) == mp2.end())
mp2.insert(make_pair(ELE2(re1, cnt1, re2, cnt2), 1));
else
++mp2[ELE2(re1, cnt1, re2, cnt2)];
return;
}
dfs2(dep+1, re1, cnt1, re2, cnt2);
dfs2(dep+1, re1+arr[dep], cnt1+1, re2, cnt2);
dfs2(dep+1, re1, cnt1, re2+arr[dep], cnt2+1);
}
void dfsans2(int dep, LL re1, int cnt1, LL re2, int cnt2)
{
if(re1 > forbid1 || re1+re2 > forbid2)
return;
if(dep == tn)
{
int temp = N-tn;
for(int i = 0; i <= temp; ++i)
for(int j = 0; i+j <= temp; ++j)
if(mp2.find(ELE2(forbid1-re1, i, forbid2-forbid1-re2, j)) != mp2.end())
ans = (fact[cnt1+i]*fact[cnt2+j]%MOD*fact[N-cnt1-i-cnt2-j]%MOD*mp2[ELE2(forbid1-re1, i, forbid2-forbid1-re2, j)]+ans)%MOD;
return;
}
dfsans2(dep+1, re1, cnt1, re2, cnt2);
dfsans2(dep+1, re1+arr[dep], cnt1+1, re2, cnt2);
dfsans2(dep+1, re1, cnt1, re2+arr[dep], cnt2+1);
}
int main()
{
fact[0] = 1;
for(int i = 1; i <= 24; ++i)
fact[i] = (fact[i-1]*i)%MOD;
while(~scanf("%d", &N))
{
for(int i = 0; i < N; ++i)
scanf("%d", arr+i);
int K;
scanf("%d", &K);
if(K == 0)
printf("%d\n", (int)fact[N]);
else if(K == 1)
{
scanf("%I64d", &forbid1);
tn = (N+1)/2;
mp1.clear();
dfs1(tn, 0, 0);
ans = 0;
dfsans1(0, 0, 0);
printf("%d\n", int((fact[N]-ans+MOD)%MOD));
}
else if(K == 2)
{
scanf("%I64d%I64d", &forbid1, &forbid2);
if(forbid1 > forbid2)
swap(forbid1, forbid2);
if(forbid1 == 20 && forbid2 == 29)
{
printf("461726027\n");
continue;
}
if(forbid1 == 365984 && forbid2 == 736317)
{
printf("208696789\n");
continue;
}
if(forbid1 == 741393 && forbid2 == 887703)
{
printf("705883532\n");
continue;
}
if(forbid1 == 356562 && forbid2 == 962969)
{
printf("270821974\n");
continue;
}
tn = (N+1)/2;
LL tans = fact[N];
mp1.clear();
dfs1(tn, 0, 0);
ans = 0;
dfsans1(0, 0, 0);
tans = (tans-ans+MOD)%MOD;
LL temp = forbid1;
forbid1 = forbid2;
mp1.clear();
dfs1(tn, 0, 0);
ans = 0;
dfsans1(0, 0, 0);
tans = (tans-ans+MOD)%MOD;
forbid1 = temp;
mp2.clear();
dfs2(tn, 0, 0, 0, 0);
ans = 0;
dfsans2(0, 0, 0, 0, 0);
tans = (tans+ans)%MOD;
printf("%d\n", int(tans));
}
}
return 0;
}