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这组两个程序得到的结果不对时,输出数据和结果,否则就一直造数据

posted @ 2021-07-22 19:19  wlhp  阅读(23)  评论(0)    收藏  举报