几校联考——day1题解

T1

约数的个数(好像不可提交)

如果一个整数a能够整除整数b,那么a叫做b的约数。
现在有N(1 <= N <= 100,000)个整数,对于其中的每一个数,请找出它在其余N - 1个整数中有多少个约数。

开个桶记录一下每个数,之后O(sqrt(n))查询即可。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<stack>
#include<cmath>

#define N 1600000
using namespace std;

int n,a[N],b[N];

int main()
{
//    freopen("A.in","r",stdin);
//    freopen("A.out","w",stdout);
    scanf("%d",&n);
    for(int i=1;i<=n;i++) scanf("%d",&a[i]);
    for(int i=1;i<=n;i++) b[a[i]]++;
    for(int k=1;k<=n;k++){
        int an=0;
        for(int i=1;i<=sqrt(a[k]);i++){
            if(!(a[k]%i)){
                if(a[k]/i==i) an+=b[i];
                else {
                    an+=b[i]+b[a[k]/i];
                    if(i==1) an-=1;
                }
            }
        }
        if(a[k]==1) an-=1;
        printf("%d\n",an);
    }
    return 0;
}

T2

P3519 [POI2011]ROZ-Difference

给一个字符串,求其中的一段,使得出现次数最多的字符与出现次数最少的字符的出现次数之差最大

暴力:随机化强行出解70

#include<bits/stdc++.h>

#define N 1600000
#define LL long long
#define inf 0x7fffffff
using namespace std;

int n,a[N],ans,sum[26][N];

void sz1() {
    for(int i=1; i<=n; i++) {
        for(int j=i+1; j<=n; j++) {
            int mx=0,mi=inf;
            for(int k=0; k<26; k++) {
                mx=max(mx,sum[k][j]-sum[k][i-1]);
                if((sum[k][j]-sum[k][i-1])) mi=min(mi,sum[k][j]-sum[k][i-1]);
            }
            ans=max(ans,mx-mi);
        }
    }
    printf("%d\n",ans);
}

void sz2() {
    for(int i=1; i<=5000000; i++) {
        int l,len,r;
        l=rand()%n+1;
        len=rand()%n+1;
//        l=1;len=rand()%n;
        r=l+len;
        r%=n;
        if(r<l) swap(l,r);
        int mx=0,mi=inf;
        for(int k=0; k<26; k++) {
            mx=max(mx,sum[k][r]-sum[k][l-1]);
            if((sum[k][r]-sum[k][l-1])) mi=min(mi,sum[k][r]-sum[k][l-1]);
        }
        ans=max(ans,mx-mi);
    }
    printf("%d\n",ans);
}

void sc3() {
    for(int i=1; i<=2; i++) {
        int l=rand()%n;
        if(i==1) l=1;
        for(int j=l+1; j<=n; j++) {
            int mx=0,mi=inf;
            for(int k=0; k<26; k++) {
                mx=max(mx,sum[k][j]-sum[k][i-1]);
                if((sum[k][j]-sum[k][i-1])) mi=min(mi,sum[k][j]-sum[k][i-1]);
            }
            ans=max(ans,mx-mi);
        }
    }
    printf("%d\n",ans);
}

int main() {
//    freopen("B.in","r",stdin);freopen("B.out","w",stdout);
    srand(time(0));
    scanf("%d",&n);
    for(int i=1; i<=n; i++) {
        char c;
        while(1) {
            c=getchar();
            if(c>='a'&&c<='z') break;
        }
        a[i]=c-'a';
    }
    for(int i=0; i<26; i++) {
        for(int j=1; j<=n; j++) {
            int x=a[j]==i?1:0;
            sum[i][j]+=sum[i][j-1]+x;
        }
    }
    if(n<=100) sz1();
    else if(n<=10000) sz2();
    else sc3();
    return 0;
}
随机化

正解:咕咕咕~~

T3

P2934 [USACO09JAN]安全出行Safe Travel

题目大意:

给你一个图,求点1到其它点的最短路,将每个点最短路径上的最后一条边删去(保证最短路径唯一),求1~该点的最短路。

以为是正解,考试时低估出题人的实力了,只有10分。

正解正在寻求中。。。

猜你喜欢

转载自www.cnblogs.com/song-/p/9612434.html