考得很炸,不是挂分太多了,主要是自己没想到,但是似乎不挂分排名还是比较好看的???
T1
水得一批,懒得讲。
T2 CF575A Fibonotci
思路
胡确实是很好胡,但是具体实现上面需要一定的技巧。于是借鉴了Rainybunny的Code
不难看出,如果没有修改操作,那么肯定是每 (n) 个数为一个循环段,每一个循环段某一个数与开头两个数相对关系确定。这个玩意就可以用矩阵进行优化。
考虑有修改,不难看出就是改了一个矩阵,具体来说可以直接拆开考虑。不过麻烦的地方就是如何考虑相邻的两处修改,其实你可以记录一下当前已经考虑了前面的多少位,通过判断当前位与修改点的关系判断这个矩阵是否被考虑到即可。具体可以见代码。
( exttt{Code})
#include <bits/stdc++.h>
using namespace std;
#define Int register int
#define int long long
#define MAXN 50005
template <typename T> inline void read (T &t){t = 0;char c = getchar();int f = 1;while (c < '0' || c > '9'){if (c == '-') f = -f;c = getchar();}while (c >= '0' && c <= '9'){t = (t << 3) + (t << 1) + c - '0';c = getchar();} t *= f;}
template <typename T,typename ... Args> inline void read (T &t,Args&... args){read (t);read (args...);}
template <typename T> inline void write (T x){if (x < 0){x = -x;putchar ('-');}if (x > 9) write (x / 10);putchar (x % 10 + '0');}
int n,m,K,lg,mod,s[MAXN];
int mul (int a,int b){return 1ll * a * b % mod;}
int dec (int a,int b){return a >= b ? a - b : a + mod - b;}
int add (int a,int b){return a + b >= mod ? a + b - mod : a + b;}
struct Matrix{
int a,b,c,d;
Matrix(){}
Matrix (int _a,int _b,int _c,int _d){a = _a,b = _b,c = _c,d = _d;}
Matrix operator * (const Matrix &p)const{return Matrix (add (mul (a,p.a),mul (b,p.c)),add (mul (a,p.b),mul (b,p.d)),add (mul (c,p.a),mul (d,p.c)),add (mul (c,p.b),mul (d,p.d)));}
}st[MAXN][65],tmp,ans;
void init (){
for (Int i = 0;i < n;++ i) st[i][0] = Matrix (0,1,s[i],s[(i + 1) % n]);
for (Int j = 1;(1ll << j) <= K;lg = j ++)
for (Int i = 0;i < n;++ i)
st[i][j] = st[(i + (1ll << j - 1)) % n][j - 1] * st[i][j - 1];
}
void getit (int& cur,int goal){
for (Int i = lg;~i;-- i)
if (cur + (1ll << i) < goal)
ans = st[cur % n][i] * ans,cur += (1ll << i);
}
#define PII pair<int,int>
PII sk[MAXN];
signed main(){
read (K,mod,n);
if (mod == 1) return puts ("0"),0;
for (Int i = 0;i < n;++ i) read (s[i]);
init ();
read (m);for (Int i = 1;i <= m;++ i){
read (sk[i].first,sk[i].second);
if (sk[i].first >= K) -- i,-- m;
}
sort (sk + 1,sk + m + 1),ans.c = 1;int cur = 0;
for (Int i = 1;i <= m;++ i){
getit (cur,sk[i].first);
if (cur < sk[i].first) tmp = Matrix (0,1,s[cur % n],sk[i].second),ans = tmp * ans,++ cur;
if (i != m && sk[i + 1].first == sk[i].first + 1) tmp = Matrix (0,1,sk[i].second,sk[i + 1].second);
else tmp = Matrix (0,1,sk[i].second,s[(cur + 1) % n]);
ans = tmp * ans,++ cur;
}
getit (cur,K);
write (cur < K ? ans.c : ans.a),putchar ('
');
return 0;
}
T3 CF480E Parking Lot
思路
原题做不出系列。。。
首先考虑 50 pts做法(我才不会告诉你我写的 (nmklog n) 结果只有 10 pts),我们不难看出可以设 (f_{i,j}) 表示以 ((i,j)) 为底部的最大正方形边长,可以得到转移式:
[f_{i,j}=min(f_{i-1,j},f_{i,j-1},f_{i-1,j-1})+1
]
考虑 100 pts,不难看出正着做不好做,于是我们可以倒着做。于是要求的就是删除一个位置,包含这个位置的最大正方形边长。
这个比较好搞,我们可以用并查集维护一下空位,然后用单调性就可以做到 (Theta(nm))。(假设并查集是线性的。)
( exttt{Code}) (一年前的代码了)
#include<bits/stdc++.h>
using namespace std;
const int maxn = 2e3 + 10;
int n,m,k;
int Ans;
int dp[maxn][maxn];
int l1[maxn];
int r1[maxn];
int qx[maxn];
int qy[maxn];
int ans[maxn];
char Map[maxn][maxn];
struct node
{
int fa[maxn];
int findSet (int x)
{
if (x == fa[x]) return x;
else return fa[x] = findSet (fa[x]);
}
}l[maxn],r[maxn];
void Delete(int x,int y)
{
l[x].fa[y] = l[x].findSet(y - 1);
r[x].fa[y] = r[x].findSet(y + 1);
}
int main()
{
scanf("%d%d%d",&n,&m,&k);
for(int i = 1; i <= n; i++)
scanf("%s", Map[i]+1);
for(int i = 1; i <= k; i++)
{
scanf("%d%d",&qx[i],&qy[i]);
Map[qx[i]][qy[i]] = 'X';
}
for(int i = 1; i <= n; i++)
{
for(int j = 1; j <= m+1; j++)
{
l[i].fa[j] = j;
r[i].fa[j] = j;
}
}
for(int i = 1; i <= n; i++)
for(int j = 1; j <= m; j++)
if(Map[i][j] == '.')
Delete(i, j);
for(int i = 1; i <= n; i++)
for(int j = 1; j <= m; j++)
if(Map[i][j] == '.')
{
dp[i][j] = min(dp[i-1][j-1], min(dp[i-1][j],dp[i][j-1]))+1;
Ans = max (Ans,dp[i][j]);
}
for (int j = k;j >= 1;-- j)
{
ans[j] = Ans;
Delete (qx[j],qy[j]);
for(int i = 1; i <= n; i++)
{
l1[i] = qy[j] - l[i].findSet(qy[j]);
r1[i] = r[i].findSet(qy[j]) - qy[j];
}
for(int i = qx[j] + 1; i <= n; i++)
{
l1[i] = min(l1[i], l1[i - 1]);
r1[i] = min(r1[i], r1[i - 1]);
}
for(int i = qx[j] - 1; i; i--)
{
l1[i] = min(l1[i], l1[i + 1]);
r1[i] = min(r1[i], r1[i + 1]);
}
for(int i = 1; i <= qx[j]; i++)
while(min(r1[i], r1[i + Ans]) + min(l1[i], l1[i + Ans]) - 1 > Ans)
Ans++;
}
for(int i = 1; i <= k; i ++)
printf("%d
",ans[i]);
return 0;
}
T4 ant
思路
不难看出 (n^6) 的高斯消元优化。
不难看出如果我们确定边界上的期望值,那我们就可以确定每一个点的 dp 值。于是拿这个解方程就可以做到 (Theta(n^3)) 了。
( exttt{Code})
#include <bits/stdc++.h>
using namespace std;
#define hash screwyourwholefamily
#define double long double
#define Int register int
#define get whysoserious
#define MAXN 205
template <typename T> inline void read (T &t){t = 0;char c = getchar();int f = 1;while (c < '0' || c > '9'){if (c == '-') f = -f;c = getchar();}while (c >= '0' && c <= '9'){t = (t << 3) + (t << 1) + c - '0';c = getchar();} t *= f;}
template <typename T,typename ... Args> inline void read (T &t,Args&... args){read (t);read (args...);}
template <typename T> inline void write (T x){if (x < 0){x = -x;putchar ('-');}if (x > 9) write (x / 10);putchar (x % 10 + '0');}
int n,m,x,y;
int hash (int x,int y){return !x ? y : m - 1 + x;}
struct node{
double a[MAXN << 1];
}get[MAXN][MAXN];
double mat[MAXN][MAXN],f[MAXN];
signed main(){
// freopen ("ant.in","r",stdin);
// freopen ("ant.out","w",stdout);
read (n,m,x,y);
for (Int i = 0;i < m;++ i) get[0][i].a[hash (0,i)] = 1;
for (Int i = 0;i < n;++ i) get[i][0].a[hash (i,0)] = 1;
for (Int i = 1;i < n;++ i)
for (Int j = 1;j < m;++ j){
for (Int k = 0;k <= n + m - 1;++ k)
get[i][j].a[k] = 0.5 * (get[i - 1][j].a[k] + get[i][j - 1].a[k]);
get[i][j].a[n + m - 1] ++;
}
int up = n + m - 1;
mat[0][0] = 1;
for (Int i = 1;i < m;++ i){
mat[hash (0,i)][hash (0,i)] = mat[hash (0,i)][up] = 2;
for (Int j = 0;j <= up;++ j) if (j != up) mat[hash (0,i)][j] -= get[0][i - 1].a[j];else mat[hash (0,i)][j] += get[0][i - 1].a[j];
for (Int j = 0;j <= up;++ j) if (j != up) mat[hash (0,i)][j] -= get[n - 1][i].a[j];else mat[hash (0,i)][j] += get[n - 1][i].a[j];
}
for (Int i = 1;i < n;++ i){
mat[hash (i,0)][hash (i,0)] = mat[hash (i,0)][up] = 2;
for (Int j = 0;j <= up;++ j) if (j != up) mat[hash (i,0)][j] -= get[i - 1][0].a[j];else mat[hash (i,0)][j] += get[i - 1][0].a[j];
for (Int j = 0;j <= up;++ j) if (j != up) mat[hash (i,0)][j] -= get[i][m - 1].a[j];else mat[hash (i,0)][j] += get[i][m - 1].a[j];
}
for (Int i = 0;i < up;++ i){
int pos = i;
for (Int j = i + 1;j < up;++ j) if (abs (mat[j][i]) > abs (mat[pos][i])) pos = j;
if (abs (mat[pos][i]) < 1e-9) continue;
if (pos ^ i) swap (mat[pos],mat[i]);
for (Int j = i + 1;j < up;++ j){
double d = mat[j][i] / mat[i][i];
for (Int k = i;k <= up;++ k) mat[j][k] -= mat[i][k] * d;
}
}
for (Int i = up - 1;~i;-- i){
for (Int j = i + 1;j < up;++ j)
mat[i][up] -= mat[i][j] * f[j];
f[i] = mat[i][up] / mat[i][i];
}
double ans = get[x][y].a[up];
for (Int i = 0;i < up;++ i) ans += get[x][y].a[i] * f[i];
printf ("%.15Lf
",ans);
return 0;
}