ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

21hdu多校二

2021-07-25 14:02:18  阅读:151  来源: 互联网

标签:int 21hdu 多校 long cin max INF dp


杭电多校第二场

1001

题意是给定一个整数边长的立方体,以其边上的整数点为顶点,有多少个等边三角形,要求三条边在三个坐标平面上。
容易得到,一个单位长度边长的立方体中有8个三角形,只有数共有多少立方体,显然为 ∑ i = 1 n − 1 i 3 \sum^{n-1}_{i=1}i^3 ∑i=1n−1​i3个

  long long inv2=qpow(2,mod-2);
  per(){
    long long n;cin>>n;
    n--;
    n%=mod;
    long long val=n*(n+1)%mod*inv2%mod;
    cout<<val*val%mod*8%mod<<endl;
  }

1005

模拟一遍即可,只有可同时在两边加时乘2,否则只能按位置放。

  per(){
    int n;cin>>n;
    cin>>in;
    ll ans=1;
    char lch=in[0];
    char rch=in[0];
    for(int i=1;i<n;++i){
      if(in[i]<lch){
        lch=in[i];
      }else if(in[i]==lch){
        if(rch==in[i]){
          ans=1ll*ans*2%mod;
        }
      }else{
        rch=in[i];
      }
    }
    cout<<ans%mod<<endl;
  }

1008

两个基础的dp的组合,先求出dp[i][j],即第i门课花j时间能获得的分数,然后利用这个结果求dp2[i][j],即挂i门课花j时间能获得的总分。
第一个dp实际是进行多个dp[j],每门课是独立的,实现时实际是dp[k][j],即前k个资料,j时间这门课能得的分,利用滚动数组变成一维。
第二个dp是二维费用的分组dp,将第i门课,花1个时间得dp[i][1]分、2个时间得d[i][2]、3个时间…t个时间得到dp[i][t]分,看成t个物品,其价值为分数,一个费用是花的时间,另一个费用是是否挂科,如果这个物品的分数低于60,费用为1,否则为0。同样有前多少个物品这一维度,用滚动数组优化掉,然后进行分组dp,注意分组dp时,遍历每个物品时不能直接修改dp数组的值,因为一组只能选一个,如果立即在dp表中修改,就会出现一组选多个,而是要比较时用dp表,当前轮的结果写入一个临时表中(这样比较时不会和这组中已经修改过的结果进行比较),一轮结束后将临时表写入dp表中。注意初始化为负无穷(0xc0)。

struct ui {int fir; int sec;};
const int maxn = 1005;
int dp[50][503];
int dp2[4][503];
int tmp[4][503];
signed main()
{
  per() {
    int n; cin >> n;
    map<string, int> ma;
    string in;
    for (int i = 1; i <= n; ++i) {
      cin >> in;
      ma[in] = i;
    }
    int m; cin >> m;
    int x, y;
    vector<ui> mts[51];
    for (int i = 1; i <= m; ++i) {
      cin >> in >> x >> y;
      mts[ma[in]].push_back(ui{x, y});
    }
    int t, p; cin >> t >> p;
    for(int i=0;i<=n;++i){
      for(int j=0;j<=502;++j){
        dp[i][j]=0;
      }
    }
    for (int c = 1; c <= n; ++c) {
      int sz = mts[c].size();
      for (int i = 0; i < sz; ++i) {
        int v = mts[c][i].fir;
        int w = mts[c][i].sec;
        for (int j = t; j >= w; --j) {
          dp[c][j] = max(dp[c][j], dp[c][j - w] + v);
        }
      }
    }
    memset(dp2,0xc0,sizeof dp2);
    dp2[0][0]=0;
    for (int i = 1; i <=n; ++i) {
      memset(tmp,0xc0,sizeof tmp);
      for (int j = t;j>=0; --j) {
        int w1 = dp[i][j] < 60 ? 1 : 0;
        int w2 = j;
        int v = min(dp[i][j],100);
        for (int w = p; w >= w1; --w) {
          for (int k = t; k >= w2; --k) {
            if (w - w1 >= 0 && k - w2 >= 0)
              tmp[w][k] = max(tmp[w][k], dp2[w - w1][k - w2] + v);
          }
        }
      }
      memcpy(dp2,tmp,sizeof tmp);
    }
    int ans=-1;
    for(int i=0;i<=p;++i){
      ans=max(ans,dp2[i][t]);
    }
    cout<<ans<<endl;
  }
}

1010

排列的逆序对满足 s g n ( π ) = ( − 1 ) n ( π ) = Π 0 ≤ j < i ≤ p − 1 π ( i ) − π ( j ) i − j sgn(\pi)=(-1)^{n(\pi)}=\Pi_{0 \leq j <i \leq p-1}\frac{ \pi(i)-\pi(j)}{i-j} sgn(π)=(−1)n(π)=Π0≤j<i≤p−1​i−jπ(i)−π(j)​,其中 n ( π ) n(\pi) n(π)为逆序对数,可以用sgn指示奇偶性, s g n sgn sgn可化为 a p − 1 2 ( m o d p ) a^{\frac{p-1}{2}}(modp) a2p−1​(modp),求其值即可。注意爆ll。

LL a,P,b;
inline long long Mul(long long x,long long y){
    long long tmp=(x*y-(long long)((long double)x/P*y+1.0e-8)*P);
    return (tmp+P)%P;
}
LL qpow(LL x,LL y){
  LL re=1,re2;
  while(y){
    if(y&1) {
      re=Mul(re,x);
    }
    x=Mul(x,x);
    y>>=1;
  }
  return re;
}
int main(){
  int t;cin>>t;
  while(t--){
    LL a;cin>>a>>P;
    cout<<(qpow(a,(P-1)/2)==1? 0:1)<<endl;
  }

}

1011

一开始的想法是dp,将当前数的某个非前缀的零变1,只从多一个1的转移,但是问题有:负数没法处理,且多出多个1的数和当前数的贡献算不进去,没法弄。
所以采用题解的做法,题解做法和我的很像,不过他不是直接转移答案,而是转移这个位置上可能用到的几个最值。我原先的做法,无法做到:对于10100,计算10100和11110的贡献,因为差了2,但是现在可以做到,如果10100和11110的贡献更大,那么会把最值转移到11100再转移到10100,就算进去了,即计算乘积最值时,应该分开维护最值,这样信息能顺着任一因子传递,而不是只能成对传递(如果想灵活传递复杂度又上去了,不只是维护,而是每一轮都遍历)。

const int INF=2e9;
const ll inf=1e18;
const int maxn=1<<20;
const int mod=998244353;
int a[maxn+10],A[maxn+10];
int b[maxn+10],B[maxn+10];
ll c[maxn+10];
signed main()
{
  per(){
    int n;
    cin>>n;
    for(int i=1;i<=n;++i){
      cin>>a[i-1];
      A[i-1]=a[i-1];
    }
    for(int i=1;i<=n;++i){
      cin>>b[i-1];
      B[i-1]=b[i-1];
    }
    int m=1;
    while(m<n){
      m<<=1;
    }
    for(int i=n;i<m;++i){
      A[i]=B[i]=-INF;
      a[i]=b[i]=INF;
    }
    for(int i=1;i<m;i<<=1){
      for(int j=m-1;j>=0;j--){
        if(!(j&i)){
          A[j]=max(A[j],A[i^j]);
          B[j]=max(B[j],B[i^j]);
          a[j]=min(a[j],a[i^j]);
          b[j]=min(b[j],b[i^j]);
        }
      }
    }
    c[n]=-inf;
    for(int i=n-1;i>=0;i--){
      c[i]=-inf;
      if(A[i]!=-INF&&B[i]!=-INF)
        c[i]=max(c[i],1ll*A[i]*B[i]);
      if(A[i]!=-INF&&b[i]!=INF)
        c[i]=max(c[i],1ll*A[i]*b[i]);
      if(a[i]!=INF&&B[i]!=-INF)
        c[i]=max(c[i],1ll*a[i]*B[i]);
      if(a[i]!=INF&&b[i]!=INF)
        c[i]=max(c[i],1ll*a[i]*b[i]);
      c[i]=max(c[i],c[i+1]);
    }
    ll ans=0;
    for(int i=0;i<n;++i){
      ans=(ans+c[i])%mod;
    }
    cout<<(ans%mod+mod)%mod<<endl;
  }
}

标签:int,21hdu,多校,long,cin,max,INF,dp
来源: https://blog.csdn.net/qq_35610768/article/details/119081063

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有