2021杭电多校第二场
1008:简单dp
struct node{
int sco, day;
node(int x = 0, int y = 0) {
sco = x; day = y;
}
}a[55][15005];
int p[55];
char s[200];
int dp1[55][102], dp2[505][4];
map<string, int> mp;
void run() {
mp.clear();
int n = rd(); int cnt = 0;
for(int i = 1; i <= n; ++ i) p[i] = 0;
for(int i = 1; i <= n; ++ i) {
scanf("%s", s); mp[s] = ++cnt;
}
int m = rd();
for(int i = 1; i <= m; ++ i) {
scanf("%s", s); int id = mp[s];
int x = rd(), y = rd();
a[id][++p[id]] = {x, y};
}
int v = rd(), gu = rd();
for(int i = 1; i <= n; ++ i) {
memset(dp1[i], 0x3f, sizeof dp1[i]); dp1[i][0] = 0;
}
for(int i = 1; i <= n; ++ i) {
for(int j = 1; j <= p[i]; ++ j) {
for(int k = 100; k >= a[i][j].sco; -- k) {
dp1[i][k] = min(dp1[i][k], dp1[i][k - a[i][j].sco] + a[i][j].day);//这个分数要最少的天数
}
}
}
for(int i = 0; i <= v; ++ i) {
memset(dp2[i], -0x3f, sizeof dp2[i]);
}
dp2[0][0] = 0;
for(int i = 1; i <= n; ++ i) {
for(int j = v; j >= 0; -- j) {//最多拿一个分数
for(int z = min(gu, i - 1); z >= 0; -- z) {//挂科
//dp[t][z] <- mx(dp[t - 及格][z] + 及格, dp[t - 不及格][z - 1] + 不及格);
//if(z == 0) dp2[j][z] = -0x3f3f3f3f3f3f3f3f;
dp2[j][z] = -0x3f3f3f3f3f3f3f3f;//必须拿一个才行,不然就是-inf(非法的状态)
for(int k = 100; k >= 0; -- k) {
if(j >= dp1[i][k]){
if(k >= 60) dp2[j][z] = max(dp2[j][z], dp2[j - dp1[i][k]][z] + k);
else if(z > 0) dp2[j][z] = max(dp2[j][z], dp2[j - dp1[i][k]][z - 1] + k);
}
}
}
}
}
int ans = -1;
for(int i = 0; i <= gu; ++ i) ans = max(ans, dp2[v][i]);
if(ans == -1) puts("-1");
else printf("%lld\n", ans);
return ;
}
1010:二次剩余的勒让德符号
求一个序列逆序对的个数在模二的意义下就是求序列的奇偶性
奇偶性就是序列的符号
\[sgn(x) = \prod_{i = 1}^n\prod_{j =i + 1}^n\frac {a_j - a_i} {|j - i|}
\]
对于此题\(a_1 a_2 a_3 ..... a_{p - 1} (a_i = i * a \pmod p)\)
\[sgn(x) =\prod_{i = 1}^n\prod_{j =i + 1}^n\frac {j * a - i * a} {|j - i|}\pmod p
\]
下面是绝对值,对符号无影响,上面提取公因子,约掉
\[sgn(x) =a^{\frac {(p-2)(p-1)} 2} \pmod p
\]
显然在模p意义下符号由a决定,即求\(a^{\frac {p-1} 2}\)在p为奇素数下的勒让德符号
inline int ksm(int a, int b) {
int res = 1;
while(b) {
if(b & 1) res = (__int128)res * a % p;
a = (__int128)a * a % p;
b >>= 1;
}
return res;
}
void run() {
a = rd(), p = rd();
int res = ksm(a, (p - 1) / 2);
if(res + 1 == p) puts("1");//-1在模p的意义下是p-1
else puts("0");
return ;
}
1004:i love count
可以借鉴上一场的1006和1010这两道题结合起来,可以用莫队去维护,每次询问的时候
类似于01字典树的询问即可。
//#include<bits/stdc++.h>
#include<cstdio>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<vector>
#include<map>
#include<stack>
#include<queue>
#include<cstring>
#include<string>
#include<set>
#include<complex>
//#include<unordered_map>
using namespace std;
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define dep(i,b,a) for(int i=b;i>=a;i--)
#define m_p make_pair
#define fi first
#define se second
#define pb push_back
#define sz(x) (int)(x).size()
#define pi acos(-1)
#define Io ios::sync_with_stdio(false);cin.tie(0)
#define io ios::sync_with_stdio(false)
#define IOS ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
typedef long long ll;
typedef pair<int,int> pii;
typedef pair<ll,ll>pll;
typedef complex<double> Comp;
const int inf=0x3f3f3f3f;
const ll INF=0x3f3f3f3f3f3f3f3f;
const double eps=1e-9;
inline int gcd(int a,int b){return b?gcd(b,a%b):a;}
inline int lcm(int a,int b){return a*b/gcd(a,b);}
namespace IO
{
const int len=4e7;char buf[len];int sz,p;
void begin(){p=0;sz=fread(buf,1,len,stdin);}
inline bool read(ll &x)
{
if (p==sz)return 0;int f=1,d=0;char s=buf[p++];
while(s<'0'||s>'9'&&p<sz){if(s=='-') f=-1;s=buf[p++];}
while(s>='0'&&s<='9'&&p<sz){d=d*10+s-'0';s=buf[p++];}
x=f*d; return p!=sz;
}
}
inline int rd()
{
int x=0,f=1;
char ch=getchar();
while(ch<'0'||ch>'9') { if(ch=='-') f=-1; ch=getchar();}
while(ch>='0'&&ch<='9') { x=(x<<1)+(x<<3)+(ch^48); ch=getchar(); }
return x*f;
}
const int maxn=1e6+50;
const int k = 333;
struct query
{
int l, r, a, b, id;
bool operator<(const query& a)const
{
return a.l / k == l / k ? r < a.r : l < a.l;
}
} q[maxn];
int a[maxn], sum[maxn], p[maxn], vis[maxn], ans[maxn];
inline void add(int x,int w)
{
sum[x / k] += w, p[x] += w;
}
inline int ask(int l,int r)
{
int bl = l / k, br = r / k;
int ans = 0;
if(bl==br)
{
// cout << l << " " << r << endl;
for (int i = l;i<=r;++i)
ans += p[i];
}
else
{
int x = bl * k + k, y = br * k;
for (int i = l; i < x;++i)
ans += p[i];
for (int i = bl + 1; i < br;++i)
ans += sum[i];
for (int i = y; i <= r;++i)
ans += p[i];
}
return ans;
}
inline int getans(int a,int b)
{
int tmp = 0, cnt = 0;
//cout << 1 << endl;
for (int i = 22; i >= 0;--i)
{
if((b>>i)&1)
{
//if(!((a>>i)&1))
if((a>>i)&1)
{
//int num = tmp;
tmp += (1 << i);
cnt += ask(tmp, tmp + (1 << i) - 1);
tmp -= (1 << i);
}else
{
cnt += ask(tmp, tmp + (1 << i) - 1);
tmp += (1 << i);
}
}else
{
if((a>>i)&1)
tmp += 1 << i;
}
}
//cout << a << " " << b << " " << tmp << endl;
cnt += ask(tmp, tmp);
return cnt;
}
void run()
{
int n = rd();
rep(i, 1, n) a[i] = rd();
int m = rd();
rep(i, 1, m) q[i].l = rd(), q[i].r = rd(), q[i].a = rd(), q[i].b = rd(), q[i].id = i;
sort(q + 1, q + 1 + m);
//rep(i, 1, m) cout << q[i].l << " " << q[i].r << endl;
int l = q[1].l, r = q[1].r;
for (int i = l; i <= r;++i)
{
// cout << i << endl;
vis[a[i]]++;
if(vis[a[i]]==1)
add(a[i], 1);
}
ans[q[1].id] = getans(q[1].a, q[1].b);
for (int i = 2;i<=m;++i)
{
int ll = q[i].l, rr = q[i].r;
while(l>ll)
{
vis[a[--l]]++;
if(vis[a[l]]==1)
add(a[l], 1);
}
while(l<ll)
{
vis[a[l]]--;
if(vis[a[l]]==0)
add(a[l],-1);
++l;
}
while(r<rr)
{
vis[a[++r]]++;
if(vis[a[r]]==1)
add(a[r], 1);
}
while(r>rr)
{
vis[a[r]]--;
if(vis[a[r]]==0)
add(a[r], -1);
--r;
}
ans[q[i].id] = getans(q[i].a, q[i].b);
}
rep(i, 1, m) printf("%d\n", ans[i]);
}
int main()
{
run();
return 0;
}
/*
start time:
over time:
*/
1011:签到题!
int un[maxn], un2[maxn], a[maxn], b[maxn], a1[maxn], b1[maxn], a2[maxn], b2[maxn], a3[maxn], b3[maxn];
inline int get(int id) {
if((a[id] >= 0 && b[id] >= 0) || (a1[id] <= 0 && b1[id] <= 0)) return 0;
return max(a2[id] * b3[id], a3[id] * b2[id]);
}
int c[maxn];
int n;
void run() {
n = rd(); int mx = -1000000000000000022ll;
for(int i = 0; i < n; ++ i) a1[i] = a[i] = un[i] = rd(), a2[i] = b2[i] = 1000000002ll;
for(int i = 0; i < n; ++ i) b1[i] = b[i] = un2[i] = rd(), a3[i] = b3[i] = -1000000002ll;
int ans = 0;
for(int i = n - 1; i >= 0; -- i) {
if(un[i] >= 0) a2[i] = min(a2[i], un[i]);
if(un2[i] >= 0) b2[i] = min(b2[i], un2[i]);
if(un[i] <= 0) a3[i] = max(a3[i], un[i]);
if(un2[i] <= 0) b3[i] = max(b3[i], un2[i]);
int add = max(max(a[i] * b[i], a1[i] * b1[i]), get(i) /*max(a[i] * b1[i], a1[i] * b[i])*/);
c[i] = mx = max(mx, add);
for(int j = 0; j <= 20; ++ j) {
if(i & (1 << j)) {
a[i - (1 << j)] = max(a[i - (1 << j)], a[i]);
b[i - (1 << j)] = max(b[i - (1 << j)], b[i]);
a1[i - (1 << j)] = min(a1[i - (1 << j)], a1[i]);
b1[i - (1 << j)] = min(b1[i - (1 << j)], b1[i]);
a2[i - (1 << j)] = min(a2[i - (1 << j)], a2[i]);
b2[i - (1 << j)] = min(b2[i - (1 << j)], b2[i]);
a3[i - (1 << j)] = max(a3[i - (1 << j)], a3[i]);
b3[i - (1 << j)] = max(b3[i - (1 << j)], b3[i]);
if(un[i] >= 0) a2[i - (1 << j)] = min(a2[i - (1 << j)], un[i]);
if(un2[i] >= 0) b2[i - (1 << j)] = min(b2[i - (1 << j)], un2[i]);
if(un[i] <= 0) a3[i - (1 << j)] = max(a3[i - (1 << j)], un[i]);
if(un2[i] <= 0) b3[i - (1 << j)] = max(b3[i - (1 << j)], un2[i]);
}
}
}
ans = 0;
int tmp = 0;
for(int i = 0; i < n; ++ i) tmp = ((tmp + c[i]) % mod + mod) % mod;
printf("%lld\n", tmp);
return ;
}
signed main() {
int t = rd();
while(t--) run();
return 0;
}
对拍程序:
const int maxn = 2e6 + 10;
const int mod = 998244353;
int un[maxn], un2[maxn], a[maxn], b[maxn], a1[maxn], b1[maxn], a2[maxn], b2[maxn], a3[maxn], b3[maxn];
inline int get(int id) {
if((a[id] >= 0 && b[id] >= 0) || (a1[id] <= 0 && b1[id] <= 0)) return 0;
return max(a2[id] * b3[id], a3[id] * b2[id]);
}
int c[maxn];
int n;
void getdata() {
srand(time(NULL));
n = rand() % 600;
int x = 1ll * rand() << 13;
for(int i = 0; i < n; ++ i) {
x = (x << 5) + x;
x = (x >> 8) + x;
x = (x << 6) + x;
x = (x >> 3) + x;
a[i] = x % mod;
}
for(int i = 0; i < n; ++ i) {
x = (x << 5) + x;
x = (x >> 8) + x;
x = (x << 6) + x;
x = (x >> 3) + x;
b[i] = x % mod;
}
}
int test() {
for(int i = 0; i < n; ++ i) c[i] = -1000000000000000022ll;
for(int k = 0; k < n; ++ k) {
for(int i = 0; i < n; ++ i) {
for(int j = 0; j < n; ++ j) {
if((i & j) >= k) {
c[k] = max(c[k], a[i] * b[j]);
}
}
}
}
int ans = 0;
for(int i = 0; i < n; ++ i) ans = (ans + c[i] % mod + mod) % mod;
return ans;
}
int run() {
int mx = -1000000000000000022ll;
for(int i = 0; i < n; ++ i) a1[i] = un[i] = a[i], a2[i] = b2[i] = 1000000002ll;
for(int i = 0; i < n; ++ i) b1[i] = un2[i] = b[i], a3[i] = b3[i] = -1000000002ll;
for(int i = n - 1; i >= 0; -- i) {
/*if(un[i] >= 0) a2[i] = min(a2[i], un[i]);
if(un2[i] >= 0) b2[i] = min(b2[i], un2[i]);
if(un[i] <= 0) a3[i] = max(a3[i], un[i]);
if(un2[i] <= 0) b3[i] = max(b3[i], un2[i]);*/
int add = max(max(a[i] * b[i], a1[i] * b1[i]), get(i) /*max(a[i] * b1[i], a1[i] * b[i])*/);
c[i] = mx = max(mx, add);
for(int j = 0; j <= 20; ++ j) {
if(i & (1 << j)) {
a[i - (1 << j)] = max(a[i - (1 << j)], a[i]);
b[i - (1 << j)] = max(b[i - (1 << j)], b[i]);
a1[i - (1 << j)] = min(a1[i - (1 << j)], a1[i]);
b1[i - (1 << j)] = min(b1[i - (1 << j)], b1[i]);
a2[i - (1 << j)] = min(a2[i - (1 << j)], a2[i]);
b2[i - (1 << j)] = min(b2[i - (1 << j)], b2[i]);
a3[i - (1 << j)] = max(a3[i - (1 << j)], a3[i]);
b3[i - (1 << j)] = max(b3[i - (1 << j)], b3[i]);
if(un[i] >= 0) a2[i - (1 << j)] = min(a2[i - (1 << j)], un[i]);
if(un2[i] >= 0) b2[i - (1 << j)] = min(b2[i - (1 << j)], un2[i]);
if(un[i] <= 0) a3[i - (1 << j)] = max(a3[i - (1 << j)], un[i]);
if(un2[i] <= 0) b3[i - (1 << j)] = max(b3[i - (1 << j)], un2[i]);
}
}
}
int tmp = 0;
for(int i = 0; i < n; ++ i) tmp = ((tmp + c[i]) % mod + mod) % mod;
return tmp;
}
signed main() {
bool f = 1;
while(f) {
getdata();
if(test() != run()) {
f = 0;
printf("%lld\n", n);
printf("%lld %lld\n", test(), run());
for(int i = 0; i < n; ++ i) printf("%lld%c", a[i], " \n"[i == n - 1]);
for(int i = 0; i < n; ++ i) printf("%lld%c", b[i], " \n"[i == n - 1]);
}
}
return 0;
}
对拍可以写三个程序,1个造数据,1个暴力,1个你的程序,while这组两个程序得到的结果不对时,输出数据和结果,否则就一直造数据

浙公网安备 33010602011771号