济南-1031试题解题报告

济南-1031试题解题报告

By shenben

本解题报告解析均为100分解题思路。

题意自行读题。(总结题意太累了……)

 

上午

T1 np

解析:打表出所有k!,其中k mod 10000000=0。询问时直接找到已知的答案,并计算不超过10000000就能找到答案。

T2 program

解析:先将ai进行排序。

f[i]表示1~i中相同的ai对数。

对于所有ai!=a{i+1}的位置,将f[i]*g*(g-1)/2累加进答案中。其中g表示存在多少数字=a{i+1}

时间复杂度nlogn

T3 select

解析:假设我们选了x行,那么必然选择了k-x列。

f[i]表示选择i行得到的最大和。考虑怎么求出所有f[i]

这个是显然可以贪心的。记录所有行的总和。利用大根对维护即可。

g[i]表示选择i列得到的最大和。

已知fg后。

答案为max{f[i]+g[k-i]-i*(k-i)*p)

 

下午

T1 chocolate

解析:

解法1:如果一个数x2的幂次,那么能得到的快乐值为x-1

因此我们可以把n拆成若干2的幂次,计算快乐值之和即可。

解法2ans=n-c(n) {c(n)表示n这个数的二进制形式上有多少个1}

T2 run

解析:二分答案,对于那些不能被到达的位置设置为障碍,问题转换成判断连通性问题

,并查集或者搜索都可以。

另外最短路也可以做。

T3 cactus

解析:观察美丽的仙人掌的定义,发现编号为ii+1之间必存在一条边,问题转化成有

若干区间,求最多的区间,使得区间之间没有重叠和覆盖。这个问题是可以直接

贪心或者dp的。

 

上午

T1代码:

#include<cstdio>
#define name "np"
#define ll long long
using namespace std;
const int a[101]={0,682498929,491101308,76479948,723816384,67347853,27368307,625544428,199888908,888050723,927880474,281863274,661224977,623534362,970055531,261384175,195888993,66404266,547665832,109838563,933245637,724691727,368925948,268838846,136026497,112390913,135498044,217544623,419363534,500780548,668123525,128487469,30977140,522049725,309058615,386027524,189239124,148528617,940567523,917084264,429277690,996164327,358655417,568392357,780072518,462639908,275105629,909210595,99199382,703397904,733333339,97830135,608823837,256141983,141827977,696628828,637939935,811575797,848924691,131772368,724464507,272814771,326159309,456152084,903466878,92255682,769795511,373745190,606241871,825871994,957939114,435887178,852304035,663307737,375297772,217598709,624148346,671734977,624500515,748510389,203191898,423951674,629786193,672850561,814362881,823845496,116667533,256473217,627655552,245795606,586445753,172114298,193781724,778983779,83868974,315103615,965785236,492741665,377329025,847549272,698611116};
const int mod=1e9+7;
const int sz=1e7;
ll n,p;
ll ans=1;
int main(){
    freopen(name".in","r",stdin);
    freopen(name".out","w",stdout);
    scanf("%I64d%I64d",&n,&p);
    if(n>=p){puts("0");return 0;}
    if(p==mod){//分段打表 
        n<sz?ans=1:ans=a[n/sz];
        for(ll i=n/sz*sz+1;i<=n;i++) ans=ans*i%p;
        printf("%I64d",ans);
        return 0;
    }
    for(ll i=1;i<=n;i++) ans=ans*i%p;
    printf("%I64d",ans);
    return 0;
} 

T2代码:

//代码优化 O(n)算法
#include<cstdio>
#include<algorithm>
#define ll long long
using namespace std;
const int N=1e5+10;
const ll mod=1e9+7;
int n,a[N];
ll ans,f[N],sum;
#define name "program"
int main(){
    freopen(name".in","r",stdin);
    freopen(name".out","w",stdout);
    scanf("%d",&n);
    for(int i=1;i<=n;i++) scanf("%d",a+i);
    sort(a+1,a+n+1);
    sum=1;f[1]=1;
    for(int i=2;i<=n;i++){
        f[i]=f[i-1];
        if(a[i]==a[i-1]){
            f[i]=f[i]-sum*sum;sum++;
            f[i]=f[i]+sum*sum;
            f[i]%=mod;
        }
        else{
            sum=1;f[i]++;
        }
    }
    sum=0;
    for(int i=n;i>1;i--){
        if(a[i]==a[i+1]) sum++;else sum=1;
        if(a[i]!=a[i-1]) ans=(ans+f[i-1]*sum%mod*sum)%mod;
    }
    printf("%d",(int)ans);
    fclose(stdin); 
    fclose(stdout); 
    return 0;
}

T3代码:

//大根堆+前缀和 贪心
#include<cstdio>
//#include<queue>
#include<algorithm>
#define ll long long
using namespace std;
const int N=1e6+10;
int n,m,k,p;
ll ans,s1[N],s2[N],p1[N],p2[N];
//priority_queue<ll>q1,q2;
#define name "select" 
int main(){
    freopen(name".in","r",stdin);
    freopen(name".out","w",stdout);
    scanf("%d%d%d%d",&n,&m,&k,&p);
    for(int i=1,t;i<=n;i++){
        for(int j=1;j<=m;j++){
            scanf("%d",&t);
            s1[i]+=t;
            s2[j]+=t;
        }
    }
    make_heap(s1+1,s1+n+1);
    make_heap(s2+1,s2+m+1);
    for(int i=1,t;i<=k;i++){
        p1[i]=p1[i-1]+s1[1];
        pop_heap(s1+1,s1+n+1);
        s1[n]-=p*m;
        push_heap(s1+1,s1+n+1);
        p2[i]=p2[i-1]+s2[1];
        pop_heap(s2+1,s2+m+1);
        s2[m]-=p*n;
        push_heap(s2+1,s2+m+1);
    }
    /*用优先队列实现好像有点问题 
    for(int i=1;i<=n;i++) q1.push(s1[i]);
    for(int i=1;i<=m;i++) q2.push(s2[i]);
    for(int i=1,t;i<=k;i++){
        t=q1.top();q1.pop();
        p1[i]=p1[i-1]+t;
        s1[n]-=p*m;
        q1.push(s1[n]);
        t=q2.top();q2.pop();
        p2[i]=p2[i-1]+t;
        s2[m]-=p*n;
        q2.push(s2[m]);
    }*/
    ll ans=-1e15;
    for(ll i=0;i<=k;i++) ans=max(ans,p1[i]+p2[k-i]-i*(k-i)*p);
    printf("%I64d",ans);
    return 0;
}
/*60分骗分代码存档 
#include<cstdio>
#include<queue>
#include<algorithm>
#define name "select"
#define ll long long
#ifdef unix
#define LL "%lld"
#else
#define LL "%I64d"
#endif
using namespace std;
inline const ll read(){
    register ll x=0,f=1;
    register char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
    return x*f;
}
const ll N=1e3+10;
ll a[N][N];
ll s1[N][N],s2[N][N];
ll n,m,k,p,sans,ans;
ll px,py;
priority_queue<ll>q;
int main(){
    //freopen("sh.txt","r",stdin);
    freopen(name".in","r",stdin);
    freopen(name".out","w",stdout);
    n=read();m=read();k=read();p=read();
    for(ll i=1;i<=n;i++){
        for(ll j=1;j<=m;j++){
            a[i][j]=read();
        }
    }
    for(ll i=1;i<=n;i++){
        for(ll j=1;j<=m;j++){
            s1[i][j]=s1[i][j-1]+a[i][j];
            s2[i][j]=s2[i-1][j]+a[i][j];
        }    
    }    
    if(k==1){
        for(ll i=1;i<=n;i++) ans=max(ans,s1[i][m]);
        for(ll i=1;i<=m;i++) ans=max(ans,s2[n][i]);
        printf(LL,ans);
        return 0; 
    }
    if(p==0){
        for(ll i=1;i<=n;i++) ans=max(ans,s1[i][m]);
        for(ll i=1;i<=m;i++) ans=max(ans,s2[n][i]);
        printf(LL,k*ans);
        return 0;
    }
    if(n==1){
        for(ll i=1;i<=m;i++) q.push(a[1][i]);
        for(ll i=1,t;i<=k;i++){
            t=q.top();q.pop();
            ans+=t;
            q.push(t-p);
        }
        printf(LL,ans);
    }
    if(n<=5&&m<=5&&k<=5){
        while(k--){
            for(ll i=1;i<=n;i++){
                for(ll j=1;j<=m;j++){
                    s1[i][j]=s1[i][j-1]+a[i][j];
                    s2[i][j]=s2[i-1][j]+a[i][j];
                }    
            }
            ans=-0x3f3f3f3f;
            for(ll i=1;i<=n;i++){
                if(ans<s1[i][m]){
                    ans=s1[i][m];
                    px=1;py=i;
                }
            }
            for(ll i=1;i<=m;i++){
                if(ans<s2[n][i]){
                    ans=s2[n][i];
                    px=2;py=i;
                }
            }
            sans+=ans;
            if(px==1){
                for(ll i=1;i<=m;i++) a[py][i]-=p;
            }
            else{
                for(ll i=1;i<=n;i++) a[i][py]-=p;
            }    
        }
        printf(LL,sans);
    }
    return 0;
}
*/

下午

T1代码:

#include<cstdio>
using namespace std;
int n,cpy,Cn;
#define name "chocolate"
int main(){
    freopen(name".in","r",stdin);
    freopen(name".out","w",stdout);
    scanf("%d",&n);
    cpy=n;
    for(;n;n>>=1) if(n&1) Cn++;
    printf("%d",cpy-Cn);
    fclose(stdin);
    fclose(stdout);
    return 0;
}
/*原始100分代码存档
#include<cstdio>
#define name "chocolate"
#define ll long long
#ifdef unix
#define LL "%lld"
#else
#define LL "%I64d"
#endif
using namespace std;
int n;
ll tot;
void dfs(ll n){
    ll i,m=1;
    if(!n||n==1) return ;
    for(i=1;;i++){
        m=1<<i;
        if(m>n) break;
    }
    m=1LL<<(i-1);
    tot+=m-1;
    dfs(n-m);
}
int main(){
    freopen(name".in","r",stdin);
    freopen(name".out","w",stdout);
    scanf(LL,&n);
    dfs(n);
    printf(LL"
",tot);
    return 0;
}
*/

T2代码:

#include<cstdio>
using namespace std;
const int N=1e6+10;
const int M=1e3+1;
int n,m,cnt,d[M][M],a[M][M],p[M][M],sx[N],sy[N],fa[N];
const int dx[4]={0,0,1,-1};
const int dy[4]={1,-1,0,0};
inline bool inside(int x,int y){
    return x>0&&x<=n&&y>0&&y<=m;
}
int find(int x){
    return fa[x]==x?x:fa[x]=find(fa[x]);
}
bool check(int x){
    for(int i=1;i<=cnt;i++) fa[i]=i;
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            if(d[i][j]>=x){
                for(int nx,ny,k=0;k<=4;k++){
                    nx=i+dx[k];
                    ny=j+dy[k];
                    if(inside(nx,ny)&&d[nx][ny]>=x){
                        fa[find(p[i][j])]=find(p[nx][ny]);
                    }
                }
            }
        }
    }
    return find(p[1][1])==find(p[n][m]);
}
int l,r,mid,ans;
#define name "run"
int main(){
    freopen(name".in","r",stdin);
    freopen(name".out","w",stdout);
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            scanf("%d",&a[i][j]);
            if(a[i][j]){
                sx[++r]=i;sy[r]=j;
                d[i][j]=1;
            }
        }
    }
    int px,py;
    while(l!=r){
        px=sx[++l];py=sy[l];
        for(int nx,ny,i=0;i<4;i++){
            nx=px+dx[i];
            ny=py+dy[i];
            if(inside(nx,ny)&&!d[nx][ny]){
                d[nx][ny]=d[px][py]+1;
                sx[++r]=nx;sy[r]=ny;
            }
        }
    }
    for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) p[i][j]=++cnt;
    l=0;r=1e6;
    while(l<=r){
        mid=l+r>>1;
        if(check(mid)) ans=mid,l=mid+1;
        else r=mid-1;
    }
    printf("%d",ans-1);
    fclose(stdin);
    fclose(stdout);
    return 0;
}

T3代码:

#include<cstdio>
#include<algorithm>
using namespace std;
const int N=1e5+10;
int n,m,g[N],f[N];
#define name "cactus"
int main(){
    freopen(name".in","r",stdin);
    freopen(name".out","w",stdout);
    scanf("%d%d",&n,&m);
    for(int i=1,x,y;i<=m;i++){
        scanf("%d%d",&x,&y);
        if(x>y) swap(x,y);
        if(x+1==y) continue;
        g[y]=max(g[y],x);
    }
    f[0]=-1;
    for(int i=2;i<=n;i++) f[i]=max(f[i-1],f[g[i]]+1);
    printf("%d",f[n]+n-1);
    fclose(stdin);
    fclose(stdout);
    return 0;
}

 

 

原文地址:https://www.cnblogs.com/shenben/p/6035573.html