UOJ Logo heqingyu的博客

博客

Day5

2018-04-07 19:41:14 By heqingyu

这次比赛估计排名和我水平差不多了,。,

%%%XRY%%%DSY

T1:

暴力出奇迹!!

code:

#include<bits/stdc++.h>
using namespace std;
int x,now;
bool check(int tot){
    int cnt1=tot%10+(tot/10)%10+(tot/100)%10;
    int cnt2=(tot/1000)%10+(tot/10000)%10+(tot/100000)%10;
    return cnt1==cnt2;
}
int main(){
    scanf("%d",&x);
    now=x+1;
    while(now<1e7){
        if(check(now)){printf("%d",now);return 0;}
        now++;
    }
    return 0;
}

T2:

比赛时第一眼就看出了是个贪心,肯定是从min走到max。。。

但是还是打了个最小生成树对拍一下。。。。

code:

#include<bits/stdc++.h>
using namespace std;
int t,n,x[110],ans;
int main(){
    scanf("%d",&t);
    while(t--){
        ans=0;
        scanf("%d",&n);
        for(int i=1;i<=n;i++)scanf("%d",&x[i]);
        sort(x+1,x+n+1);
        for(int i=1;i<n;i++)ans+=abs(x[i+1]-x[i]);
        printf("%d\n",ans);
    }
    return 0;
}

T3:

我们记fa[i]表示A数组中有无i的倍数,fb[i]表示B数组中有无i的倍数

然后我们枚举对于每个A,B,预处理出fa,fb数组(sqrt(A)的复杂度)

接着枚举i,如果fa[i]与fb[i]同时为true时,说明i满足gcd,更新答案

最后O(n)扫一遍,求出最大的x+y即可

code:

#include<bits/stdc++.h>
using namespace std;
int n,A[500010],B[500010],fa[1000010],fb[1000010];
int ans;
void solve1(int x){
    for(int i=1;i<=sqrt(x);i++){
        int k=x/i;
        if(x%i==0){fa[i]++;fa[k]++;}
    }
    return;
}
void solve2(int x){
    for(int i=1;i<=sqrt(x);i++){
        int k=x/i;
        if(x%i==0){fb[i]++;fb[k]++;}
    }
    return;
}
int tot,ansa,ansb;
int main(){
    freopen("gcd.in","r",stdin);
    freopen("gcd.out","w",stdout);
    scanf("%d",&n);
    for(int i=1;i<=n;i++)scanf("%d",&A[i]),solve1(A[i]);
    for(int i=1;i<=n;i++)scanf("%d",&B[i]),solve2(B[i]);
    for(int i=1000000;i>=1;i--)if(fa[i]&&fb[i]){tot=i;break;}
    for(int i=1;i<=n;i++)if(A[i]%tot==0) ansa=max(ansa,A[i]);
    for(int i=1;i<=n;i++)if(B[i]%tot==0) ansb=max(ansb,B[i]);
    printf("%d",ansa+ansb);
    return 0;
}

T4:

考虑品牌数量极少,可以直接二分+暴力check

首先把物品按价格sort,接下来设s1[i]表示比i物品便宜的,品牌为1的物品数量,其他以此类推

然后二分物品标号,check的话就把所有物品标号<=mid且品牌被XXX所喜爱的加起来

如果数量小于k,那么说明需要价格更高的,l=mid+1;

否则的话就r=mid-1;

code:

#include<bits/stdc++.h>
#define fi first
#define se second
using namespace std;
int n,q,d,k,brand[6];
struct node{
    int b,p;
}a[100010];
int s1[100010],s2[100010],s3[100010],s4[100010],s5[100010];
bool cmp(node x,node y){return x.p<y.p;}
int check(int x){
    int cnt=0;
    for(int i=1;i<=d;i++){
        if(brand[i]==1) cnt+=s1[x];
        if(brand[i]==2) cnt+=s2[x];
        if(brand[i]==3) cnt+=s3[x];
        if(brand[i]==4) cnt+=s4[x];
        if(brand[i]==5) cnt+=s5[x];
    }
    return cnt;
}
int main(){
    scanf("%d",&n);
    for(int i=1;i<=n;i++)scanf("%d",&a[i].b);
    for(int i=1;i<=n;i++)scanf("%d",&a[i].p);
    sort(a+1,a+n+1,cmp);
    for(int i=1;i<=n;i++){
        if(a[i].b==1) s1[i]=s1[i-1]+1;else s1[i]=s1[i-1];
        if(a[i].b==2) s2[i]=s2[i-1]+1;else s2[i]=s2[i-1];
        if(a[i].b==3) s3[i]=s3[i-1]+1;else s3[i]=s3[i-1];
        if(a[i].b==4) s4[i]=s4[i-1]+1;else s4[i]=s4[i-1];
        if(a[i].b==5) s5[i]=s5[i-1]+1;else s5[i]=s5[i-1];
    }
    scanf("%d",&q);
    int ans=0;
    while(q--){
        ans=0;
        scanf("%d",&d);
        for(int i=1;i<=d;i++)scanf("%d",&brand[i]);
        scanf("%d",&k);
        if(check(n)<k){puts("-1");continue;}
        int l=1,r=n;
        ans=-1;
        while(l<=r){
            int mid=l+r>>1;
            if(check(mid)>=k) r=mid-1;
            else l=mid+1;
        }
        printf("%d\n",a[l].p);
    }
    return 0;
}

T5:

设f[i][j][k]表示A串前i个字符,B串前j个字符,LCS至少为K的最小代价

考虑对于i和j,有三种决策:

1.修改i,使其变成j,代价为i^j

2.对于第i个,跳过,不放入LCS

3.对于第j个,跳过,不放入LCS

code:

#include<bits/stdc++.h>
using namespace std;
int n,m,k,f[360][360][360];
char A[360],B[360];
int solve(int a,int b,int c){
    if(!c) return 0;
    if(!a||!b||!c) return 1e9;
    if(f[a][b][c]!=-1) return f[a][b][c];
    int cos=(A[a]-'a')^(B[b]-'a');
    return f[a][b][c]=min(cos+solve(a-1,b-1,c-1),min(solve(a-1,b,c),solve(a,b-1,c)));
}
int main(){
    scanf("%d%d%d",&n,&m,&k);
    memset(f,-1,sizeof(f));
    scanf("%s%s",A+1,B+1);
    if(solve(n,m,k)==1e9) puts("-1");
    else printf("%d",solve(n,m,k));
    return 0;
}

T6:

这题的标算是线段树,没有敲。。敲了一个玄学暴力。。于是只讲做法。。。

发现如果x>=40,则x!%1e9==0

所以只需要考虑小于40的所有数,这些数用线段树来维护即可(说起来真简单)

暴力code:

#include<bits/stdc++.h>
#define ll long long
using namespace std;
ll a[1000010],n,m,p,l,r;
ll jie[41];
const int mod=1e9;
int main(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)scanf("%d",&a[i]);
    jie[0]=1;
    for(int i=1;i<=40;i++)jie[i]=(ll)jie[i-1]*i%mod;
    while(m--){
        ll cnt=0;
        scanf("%d%d%d",&p,&l,&r);
        if(p==1) for(int i=l;i<=r;i++) a[i]++;
        if(p==2) for(int i=l;i<=r;i++){cnt+=a[i]>40?0:jie[a[i]];cnt%=mod;}
        if(p==3) a[l]=r;
        if(p==2) printf("%lld\n",cnt);
    }
    return 0;
}

评论

暂无评论