上海站
C题是典型的数位DP,我把这道题做出来之后才去开了济南的L
大概就是用两个布尔维度表示一下是否卡上界,然后做一下记忆化搜索
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int t, X, Y;
const int maxn = 32;
const ll mod = 1e9 + 7;
int xx[maxn], yy[maxn];
int lx, ly;
ll dp[maxn][2][2];
ll solve(int p, bool x, bool y)
{
if (p == -1)
return 1ll;
if (dp[p][x][y] != -1)
return dp[p][x][y];
int xlim = x ? 1 : xx[p];
int ylim = y ? 1 : yy[p];
ll ans = 0;
for (int i = 0; i <= xlim; ++i)
{
for (int j = 0; j <= ylim; ++j)
{
if (i & j)
continue;
ans += solve(p - 1, x | (i < xlim), y | (j < ylim));
ans %= mod;
}
}
dp[p][x][y] = ans;
return ans;
}
int i2v(int n, int *v)
{
int i = -1;
for (; n; n >>= 1)
{
i++;
v[i] = n & 1;
}
return i;
}
int main()
{
// freopen("cin", "r", stdin);
for (scanf("%d", &t); t--;)
{
memset(dp, -1, sizeof(dp));
memset(xx, 0, sizeof(xx));
memset(yy, 0, sizeof(yy));
scanf("%d%d", &X, &Y);
lx = i2v(X, xx);
ly = i2v(Y, yy);
ll ans = 0;
for (int i = 0; i <= lx; ++i)
ans = (ans + solve(i - 1, i < lx, i <= ly) * (i + 1)) % mod;
for (int j = 0; j <= ly; ++j)
ans = (ans + solve(j - 1, j <= lx, j < ly) * (j + 1)) % mod;
printf("%lld\n", ans);
}
return 0;
}
I题是道计数,场上那会儿被特判卡了没A出来
参考逆十字的思路,没压缩复杂度,硬搞了
O
(
n
3
)
O(n^3)
O(n3)的循环
#include <bits/stdc++.h>
using namespace std;
typedef long double ld;
int n, m;
ld ans;
ld pi = acos(-1);
int main()
{
scanf("%d%d", &n, &m);
ans = 0;
for (int k = 1; k <= m; ++k)
{
ld dis = min((ld)2.0, pi / m * k);
ld delta;
for (int i = 1; i <= n; ++i)
{
for (int j = i; j <= n; ++j)
{
if (k == m)
delta = 2 * j;
else
delta = (dis * i + (j - i)) * 2;
if (j != i)
delta *= 2;
delta *= 2 * m;
ans += delta;
}
}
}
if (m != 1)
{
for (int i = 1; i <= n; ++i)
ans += (ld)4 * m * i;
}
printf("%.10Lf\n", ans / 2);
return 0;
}
济南站
L题也是数位DP,这个比较难顶,需要稍微分类讨论一下下
但是状态比较复杂,需要枚举后七位的可能值,并且讨论是否存在进位的情况。
根据题解,发现只需要枚举第七位以上连续1的奇偶性,7位以上所有数字的奇偶性即可
且枚举7以下位数的过程可以作为边界条件单独计算,可以略去这一维度
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int m, t, n;
const int maxn = 105, maxb = 64;
ll L;
int l[maxb], a[maxn];
ll rslt[2][2][2];
ll dp[maxb][2][2][2];
// [pos][sum][0~6][even]
ll calc(int lim, int s, int t)
{
ll ans = 0, x = lim ? L % 128 : 127;
for (int j = 0; j <= x; ++j)
{
bool flag = 1;
for (int i = 0; i < m; ++i)
{
bool tmp = __builtin_parity(i + j) ^ s;
if (i + j >= 128)
tmp ^= t;
if (tmp != a[i])
{
flag = 0;
break;
}
}
if (flag)
ans++;
}
return ans;
}
ll dfs(int pos, int lim, int s, int t)
{
ll &d = dp[pos][lim][s][t];
if (d != -1)
return d;
if (pos < 7)
{
d = rslt[lim][s][t];
return d;
}
d = 0;
int I = lim ? l[pos] : 1;
for (int i = 0; i <= I; ++i)
d += dfs(pos - 1, lim & (i == I), s ^ i, i & (!t));
return d;
}
ll solve()
{
memset(dp, -1, sizeof(dp));
n = -1;
for (ll tmpl = L; tmpl; tmpl >>= 1)
l[++n] = tmpl & 1;
for (int i = 0; i < 8; ++i)
rslt[i & 1][(i >> 1) & 1][(i >> 2) & 1] = calc(i & 1, (i >> 1) & 1, (i >> 2) & 1);
return dfs(n, 1, 0, 0);
}
int main()
{
// freopen("lin", "r", stdin);
scanf("%d", &t);
for (int tmp; t--;)
{
scanf("%d%lld", &m, &L);
for (int i = 0; i < m; ++i)
scanf("%d", &a[i]);
printf("%lld\n", solve());
}
return 0;
}