昨晚修仙,今天这场确实打到一半就打不动了。反正也是一人一队,干脆后半场摸鱼。
所以最后就搞了三道水题(哭
就是这题做了我半天。
一开始感觉 O ( n k ) O(nk) O(nk)有 1 e 7 1e7 1e7可能过不了,不过大哥说0.3s能过,然后我就大胆写了。
这题考虑一个 d p dp dp,设长度为 k k k的串为 a a a,另一个为 b b b, d p [ i ] [ j ] dp[i][j] dp[i][j]为 a a a串前 i i i个与 b b b串前 j j j个匹配所得到的结果,那么有 d p [ i ] [ j ] = { d p [ i ] [ j − 1 ] , a [ i ] ! = b [ j ] d p [ i ] [ j − 1 ] + d p [ i − 1 ] [ j − h [ a [ i − 2 ] − ′ A ′ ] − 1 ] , a [ i ] = = b [ j ] dp[i][j]=\begin{cases} dp[i][j-1], a[i]!=b[j]\\ dp[i][j-1]+dp[i-1][j-h[a[i-2]-'A']-1], a[i]==b[j] \end{cases} dp[i][j]={dp[i][j−1],a[i]!=b[j]dp[i][j−1]+dp[i−1][j−h[a[i−2]−′A′]−1],a[i]==b[j]
其中 h [ i ] h[i] h[i]记录的是距离的时间。
这方程很好推,本来应该最多半小时切掉的,结果没想到这坑爹题目上面的数据范围是 n , k n,k n,k这么给的,下面输入是 k , n k,n k,n这么给的。看反之后找了半天问题。
另外就是好不容易写好了一直WA3,后来群里说是题目数据错了…结果为了加大空间还搞了个滚动数组。
打完返回Problems面板才发现下面写了个数据错误的公告。
#include
using namespace std;
typedef long long ll;
const int MAXN = 1e7 + 10, MAXK = 1e7 + 10;
const int MOD = 1e9 + 7;
int main()
{
int n, k; cin >> k >> n;
static int dp[2][MAXN];
dp[0][0] = dp[1][0] = 0;
int h[26];
for (int i = 0; i < 26; ++i) scanf("%d", h + i);
string a, b; cin >> a >> b;
for (int i = 1; i <= n; ++i)
{
dp[1][i] = dp[1][i - 1];
if (a[0] == b[i - 1]) ++dp[1][i];
}
int cnt = 1;
for (int i = 2; i <= k; ++i)
{
cnt ^= 1;
for (int j = 1; j <= n; ++j)
{
dp[cnt][j] = dp[cnt][j - 1];
if (a[i - 1] == b[j - 1])
{
if (j - h[a[i - 2] - 'A'] - 1 >= 0)
dp[cnt][j] = (dp[cnt][j] + dp[cnt ^ 1][j - h[a[i - 2] - 'A'] - 1]) % MOD;
}
}
}
/*for (int i = 1; i <= k; ++i)
{
for (int j = 1; j <= n; ++j)
cout << dp[i][j] << ' ';
cout << endl;
}*/
cout << dp[cnt][n] << endl;
return 0;
}
本来之后想做个D,结果交上去一直WA。想了半天算法没问题,可能是我理解错了。
物理题,算一算就好了。
#include
using namespace std;
typedef long long ll;
const int MAXN = 1e4 + 10;
struct node
{
int a, t;
};
bool cmp(node a, node b)
{
return a.a > b.a;
}
int main()
{
int n; cin >> n;
node a[MAXN];
for (int i = 1; i <= n; ++i) scanf("%d%d", &a[i].a, &a[i].t);
int v = 0; double x0 = 0, x1 = 0;
for (int i = 1; i <= n; ++i)
{
x0 += v * a[i].t + a[i].a * a[i].t * a[i].t / 2.0;
v += a[i].a * a[i].t;
}
v = 0;
sort(a + 1, a + 1 + n, cmp);
for (int i = 1; i <= n; ++i)
{
x1 += v * a[i].t + a[i].a * a[i].t * a[i].t / 2.0;
v += a[i].a * a[i].t;
}
printf("%.1f\n", x1 - x0);
return 0;
}
这题也卡了我好久。一开始的想法是去找还没用过的数字里第 a [ i ] a[i] a[i]大的数,但是这 O ( n 2 ) O(n^2) O(n2)铁超。后来用个玄学排序过了。大概就是越长数字越小,然后长度相同的把后面的赋成更小的值。(因为如果后面比前面大可能会和前面矛盾)
#include
using namespace std;
typedef long long ll;
const int MAXN = 1e5 + 10;
struct node
{
int index, len, v;
};
bool cmp1(node a, node b)
{
if (a.len == b.len) return a.index > b.index;
else return a.len > b.len;
}
bool cmp2(node a, node b)
{
return a.index < b.index;
}
int main()
{
int n; cin >> n;
node a[MAXN];
for (int i = 1; i <= n; ++i)
{
scanf("%d", &a[i].len);
a[i].index = i;
}
sort(a + 1, a + 1 + n, cmp1);
for (int i = 1; i <= n; ++i) a[i].v = i;
sort(a + 1, a + 1 + n, cmp2);
for (int i = 1; i <= n; ++i) cout << a[i].v << ' ';
cout << endl;
return 0;
}