集训的第2次考试

5.31又考了一次试。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。

 题1:

 一道大水题就过吧;

 题2(好大的Gcd(gcd.cpp)):

题目描述

       定义一个6位数是lucky的,当且仅当它的前3位之和等于后3位之和,比如165912

       给出数x,找出最小的、大于x的幸运数字。

       无解输出-1.

格式

       输入:一个数,表示x

       输出:一个数,表示下一个幸运数字

范围:

      

Sample Input 0

555555

Sample Output 0

555564
只想到暴力辗转相除法再加点点点点的优化只拿了30分;后来知道了可以分别找出两个式子的各个因式上的最大值

 

#include<bits/stdc++.h>
using namespace std;
inline int read()
{
    int x=0,w=0;
    char ch=0;
    while(!isdigit(ch)) {w|=ch=='-';ch=getchar();}
    while(isdigit(ch)) {x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
    return w? -x:x;
}
const int N=1e6+6;
int n,j,c1,c2;
int a[1001000],b[1001000],c[N],aa[N],bb[N];
#define fr(x) for(int i=1;i<=n;i++)
int main()
{
    n=read();
 
    for(int i=1;i<=n;i++)
      a[i]=read();
    for(int i=1;i<=n;i++)
      b[i]=read();  
    for(int i=1;i<=n;i++)
      c[a[i]]++;
    for(int i=1;i<N;i++)
      for(int o=i;o<N;o+=i)
        if(c[o])
          aa[i]=max(aa[i],o);
    for(int i=1;i<=n;i++)
      c[a[i]]--; 
    for(int i=1;i<=n;i++)
      c[b[i]]++;   
    for(int i=1;i<N;i++)
      for(int o=i;o<N;o+=i)
        if(c[o])
          bb[i]=max(bb[i],o);
    int dd=0;
    for(int i=1;i<=1e6+7;i++)
      if(aa[i]&&bb[i])
        dd=i;
    cout<<aa[dd]+bb[dd];
    return 0;
}
 
 
 
 
 
 
 
 
 
 
 
 

 题3(买买买):

题目描述

       蓝月商场有n件宝贝,每件宝贝有两个属性:价钱price和品牌brand。其中brand是1-5之间某个整数。每件宝贝价钱两两不同。

       贪玩蓝月有Q个代言人,每个代言人拍完戏之后,希望能从蓝月商场免费顺走一样宝贝。但是每个代言人有自己的喜好,例如古天乐只喜欢品牌1,陈小春喜欢品牌1或品牌2,渣渣辉喜欢品牌3和5……具体来说,代言人会有d个喜欢的品牌(1 <= d <= 5),同时他最喜欢这些品牌中,价钱第k便宜的宝贝。

       请你求出每个代言人最喜欢的宝贝的价钱是多少!如果不存在这件宝贝,请输出-1.

格式

       输入:第一行一个整数n,第二行n个整数描述每件宝贝的品牌,第三行n个数描述每件宝贝的价钱。第四行一个整数Q,接下来Q*3行,每3行描述一个代言人的信息。其中第一行一个整数d,第二行d个数表示喜欢的品牌,第三行一个数表示k。

       输出:一共Q行,每行一个数。

范围:

      

Sample Input 0

3
1 1 2
1 3 2
3
1
1
2
2
1 2
2
1
3
1

Sample Output 0

3
2
-1
我先是快速排序在算出各个品牌的总共多少接着从大到小暴力枚举假如小于最大因数就退出。。50分
后来知道要求各个的前缀和再二分答案;
#include<bits/stdc++.h>
using namespace std;
inline int read()
{
    int x=0,w=0;
    char ch=0;
    while(!isdigit(ch)) {w|=ch=='-';ch=getchar();}
    while(isdigit(ch)) {x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
    return w? -x:x;
}
#define s(x,y) sort(x+1,x+y+1)
struct xin
{
    int p,v;
}w[100010];
bool pd(xin a,xin b)
{
    return (a.v<b.v);
}
int n,q,z,pz[10],k,pp[10],s1[100010],s2[100010],s3[100010],s4[100010],s5[100010];
inline int get(int k)
{
    int j=0;
    for(int i=1;i<=z;i++)
    {
        if(pz[i]==1) j+=s1[k]; 
        if(pz[i]==2) j+=s2[k]; 
        if(pz[i]==3) j+=s3[k]; 
        if(pz[i]==4) j+=s4[k]; 
        if(pz[i]==5) j+=s5[k];
    }
    return j;
} 
int main()
{
    n=read();
    for(int i=1;i<=n;i++)
        w[i].p=read();  
    for(int i=1;i<=n;i++)
        w[i].v=read();
    sort(w+1,w+1+n,pd);
    for(int i=1;i<=n;i++)
    {
        if(w[i].p==1) s1[i]=s1[i-1]+1; else s1[i]=s1[i-1];
        if(w[i].p==2) s2[i]=s2[i-1]+1; else s2[i]=s2[i-1];
        if(w[i].p==3) s3[i]=s3[i-1]+1; else s3[i]=s3[i-1];
        if(w[i].p==4) s4[i]=s4[i-1]+1; else s4[i]=s4[i-1];
        if(w[i].p==5) s5[i]=s5[i-1]+1; else s5[i]=s5[i-1];
    }
    q=read();
    for(int i=1;i<=q;i++)
    {
        z=read();
        for(int o=1;o<=z;o++)
            pz[o]=read();
        k=read();
        if(get(n)<k)
        {
            printf("-1\n");
            continue;
        } 
        
        int l=1,r=n;int mid;
        while(l<=r)
        {
            mid=(l+r)>>1;
            if(get(mid)>=k)
                r=mid-1;
            else
                l=mid+1;
        }
        printf("%d\n",w[l].v);
    }
    return 0;
}

 题4(干爆字符串):,,,,

 

题目描述

 

       有两个仅包含小写字母的字符串x,y,长度分别为n,m。你需要修改x串中某些字符,是的新的x串和y串的最长公共子序列长度至少为k。

 

       我们将’a’…’z’对应成0…25,修改两个字符付出的代价,为它们对应的数的xor值。比如说,将’a’修改成’z’代价为0 xor 25=25。

 

       请问最少付出多少代价,使得新的x串和y串的LCS大于等于k。

 

格式

 

       输入:第一行三个数n,m,k,第二行长度为n的字符串x,第三行长度为m的字符串y。

 

       输出:最小花费,如果不能请输出-1。

 

范围:

 

 

SampleInput 0

 

7 4 2

 

merging

 

pair

 

SampleOutput 0

 

3

因为看见字符串匹配就不舒服(于是就跳了)水样例和特判-1拿了15;
后来知道是3维DP 三种情况
#include<bits/stdc++.h>
 
using namespace std;
 
const int M=1e9;
 
int a[555],b[555],f[555][555][2];
 
int main()
 
{
 
int n,m,k;
 
cin>>n>>m>>k;
 
string x,y;
 
if(k>min(n,m))
 
{
 
cout<<-1;return 0;
 
}
 
cin>>x>>y;
 
for(int i=n;i>=1;i--)
 
a[i]=x[i-1]-97;
 
for(int i=m;i>=1;i--)
 
b[i]=y[i-1]-97;
 
for(int i=0;++i<=k;)
 
{
 
f[0][0][i&1]=M;
 
for(int o=0;++o<=n;)
 
f[o][0][i&1]=M;
 
for(int o=0;++o<=m;)
 
f[0][o][i&1]=M;
 
for(int o=0;++o<=n;)
 
for(int p=0;++p<=m;)
 
f[o][p][i&1]=min(min(f[o][p-1][i&1],f[o-1][p][i&1]),f[o-1][p-1][(i&1)^1]+(a[o]^b[p]));
 
}
 
cout<<f[n][m][k&1];
 
return 0;
 
}

题5(阶乘数组):

题目描述

       给出长度为n的序列A1,A2,…,An。进行m次操作,有三种类型:

  1. 给出l,r,将区间[l,r]的Ai都加一。

  2. 阶乘数组给出l,r,询问区间[l,r]的Ai!的和,对10^9取模。

  3. 给出I,v,将Ai单点修改为v。

格式

       输入第一行两个数n,m,第二行n个数Ai。

接下来m行,每行三个数,第一个数k,表示第几类操作,后面两个数如题所述。

输出:对于每个操作2输出解。

范围

      

Sample Input 0

5 7
1 1 1 1 1
2 1 5
1 1 5
2 1 5
1 1 3
2 1 5
3 1 15
2 1 5

Sample Output 0

5
10
22
674368016
最难过的一道,一半左右的时间都在做这一道,还爆零了。
1.查错时的输出没删掉!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
(与是连直接水样例可以拿的15都没有)
2.没有发现(打表)40及以后%1e9都为零

3.线段树极其不熟练,想着用树状数组写(比较好写也稍微熟练些)but(考试完后修改还遇到的不可抗拒性的错误,还超时了一个)(??为什么会比线段树慢)

#include <bits/stdc++.h>
 
using namespace std;
 
#define ll long long
 
const int N=1e6,P=1e9;
 
int n,m,s;
 
int a[N],t[N],b[41];
 
struct hh
 
{
 
int l,r,n[41],z;
 
}tr[N];
 
ll v[50]={0,1,2,6,24,120,720,5040,40320,362880,
 
3628800,39916800,479001600,227020800,178291200,
 
674368000,789888000,428096000,705728000,408832000,
 
176640000,709440000,607680000,976640000,439360000,
 
984000000,584000000,768000000,504000000,616000000,
 
480000000,880000000,160000000,280000000,520000000,
 
200000000,200000000,400000000,200000000,800000000,0};
 
ll A;
 
 
 
#define C getchar()-48
 
inline int read()
 
{
 
int s=0,t=1,k=C;
 
for (;k<0||k>9;k=C) if (k==-3) t=-1;
 
for (;k>=0&&k<=9;k=C) s=(s<<1)+(s<<3)+k;
 
return s*t;
 
}
 
inline void write(long long x)
 
{
 
if(x<0) putchar('-'),x=-x;
 
if(x>9) write(x/10);
 
putchar(x%10+'0');
 
}
 
void fir()
 
{
 
v[1]=1;
 
for (int i=1;++i<40;)
 
v[i]=(v[i-1]*i)%P;
 
}
 
 
 
#define ls k<<1
 
#define rs k<<1|1
 
inline void bt(int k,int l,int r) //建树
 
{
 
tr[k].l=l;tr[k].r=r;
 
if (l==r) return;
 
int M=l+r>>1;
 
bt(ls,l,M);bt(rs,M+1,r);
 
}
 
//上到下传递值
 
inline void dow(int k)
 
{
 
int z=tr[k].z;
 
if (!z) return;
 
for (int i=40;--i;)
 
{
 
if (i+z<40)
 
tr[ls].n[i+z]+=tr[ls].n[i],
 
tr[rs].n[i+z]+=tr[rs].n[i];
 
tr[ls].n[i]=tr[rs].n[i]=0;
 
}
 
tr[ls].z+=z;
 
tr[rs].z+=z;
 
tr[k].z=0;
 
}
 
//下到上传递值
 
inline void ud(int k)
 
{
 
for (int i=40;--i;)
 
tr[k].n[i]=tr[ls].n[i]+tr[rs].n[i];
 
}
 
//读入
 
inline void into1(int k,int l,int s)
 
{
 
if (l>tr[k].r||l<tr[k].l) return;
 
if (tr[k].l==tr[k].r)
 
{
 
for (int i=40;--i;)
 
tr[k].n[i]=0;
 
if (s<40) tr[k].n[s]=1;
 
return;
 
}
 
dow(k);
 
into1(ls,l,s);
 
into1(rs,l,s);
 
ud(k);
 
}
 
//读入
 
inline void into2(int k,int l,int r)
 
{
 
if (l>tr[k].r||r<tr[k].l) return;
 
if (l<=tr[k].l&&tr[k].r<=r)
 
{
 
dow(k);
 
for (int i=40;--i>=0;)
 
tr[k].n[i+1]=tr[k].n[i];
 
++tr[k].z;
 
return;
 
}
 
dow(k);
 
into2(ls,l,r);
 
into2(rs,l,r);
 
ud(k);
 
}
 
//累加
 
inline void qwe(int k,int l,int r)
 
{
 
if (l>tr[k].r||r<tr[k].l) return;
 
if (l<=tr[k].l&&tr[k].r<=r)
 
{
 
for (int i=40;--i;)
 
b[i]+=tr[k].n[i];
 
return;
 
}
 
dow(k);
 
qwe(ls,l,r);
 
qwe(rs,l,r);
 
}
 
 
 
int main()
 
{
 
cin>>n>>m;
 
bt(1,1,n);
 
for (int i=0;++i<=n;)
 
{
 
a[i]=read();
 
if (a[i]<40) into1(1,i,a[i]);
 
}
 
 
 
while (m--)
 
{
 
int z=read(),x=read(),y=read();
 
if (z==1)
 
{
 
if (x>y) swap(x,y);
 
纪念我的树状数组
 
                     ///////////// 
                     ////%%%%%////
                     ////%%%%%////
                     ////%%%%%//// 
                     ////%%%%%//// 
             ////////////%%%%%//////////// 
             ////%%%%%%%%%%%%%%%%%%%%%//// 
             ////%%%%%%%%%%%%%%%%%%%%%//// 
             ////////////%%%%%//////////// 
                     ////%%%%%//// 
                     ////%%%%%//// 
                     ////%%%%%////
                     ////%%%%%////
             //////%%%%%%%%%%%%%%%%%//////
         ////%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%////
      ////%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%////
   ///%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%///
   ///%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%///
   ///%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%///
   ///%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%///
   ///%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%///
///%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%/// ///%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%/// ///%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%/// ///%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%/// ///%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%/// ///%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%/// ///%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%/// ///%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%/// ///%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%/// ///%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%/// ////////////////////////////////////////////////// |********************************************************| |********************************************************| MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM --------------------------------------------------------------- #include<bits/stdc++.h> using namespace std; inline int read() { int x=0,w=0; char ch=0; while(!isdigit(ch)) {w|=ch=='-';ch=getchar();} while(isdigit(ch)) {x=(x<<3)+(x<<1)+(ch^48);ch=getchar();} return w? -x:x; } inline void write(long long x) { if(x<0) putchar('-'),x=-x; if(x>9) write(x/10); putchar(x%10+'0'); } #define cc 1000000000 #define ll long long int n,m; int a[2000000]; ll k,l,r; ll c[1000100]; ll v[50]={0,1,2,6,24,120,720,5040,40320,362880, 3628800,39916800,479001600,227020800,178291200, 674368000,789888000,428096000,705728000,408832000, 176640000,709440000,607680000,976640000,439360000, 984000000,584000000,768000000,504000000,616000000, 480000000,880000000,160000000,280000000,520000000, 200000000,200000000,400000000,200000000,800000000,0}; inline int lowbit(int k){ return (k&(-k)); } inline void into(int a,int k) { while(a<=n) { while(c[a]+k<0) c[a]+=cc; c[a]=(c[a]+k)%cc;a+=lowbit(a); } } inline ll out(int k) { ll z=0; while(k>0) { z=(z+c[k])%cc;k-=lowbit(k); } return z; } int main() { n=read(),m=read(); for(int i=1;i<=n;i++) { a[i]=read(); if(a[i]<40) into(i,a[i]); } for(int i=1;i<=m;i++) { k=read();l=read();r=read(); if(k==1) { for(int o=l;o<=r;o++) { a[o]++; if(a[o]==40) into(o,-v[39]); if(a[o]>40) continue; if(a[o]<40) into(o,(v[a[o]]-v[a[o]-1])%cc); } } if(k==2) { write(out(r)-out(l-1));printf("\n"); } if(k==3) { if(r>=40) r=40; into(l,(v[r]-v[a[l]])%cc); a[l]=40; } } return 0; } */


into2(1,x,y); } if (z==2) { A=0; memset(b,0,sizeof b); if (x>y) swap(x,y); qwe(1,x,y); for (int i=40;--i;) A=(A+v[i]*b[i]%P)%P; write(A);printf("\n"); } if (z==3) into1(1,x,y); } return 0;}

题6(二进制操作数组):

 

题目描述

输入格式

输出格式

数据范围

      

Sample Input 0

6 6
8 9 1 13 9 3
1 4 5
2 6 9
1 3 7
2 7 7
1 6 1
2 11 13

Sample Output 0

45
19
21
 暴力40.。。。。。。。。。。。。
还没做出来。。。。。。

猜你喜欢

转载自www.cnblogs.com/1436177712qqcom/p/9254184.html