江西理工大学摸底测试题解

江西理工大学摸底测试题解

A: Water

思路:用一个数组add[i]记录第i个位置上加的总的水量,用一个sum维护当前的总水量,从前往后遍历,每次加上add[i]后于容量比较即可。

AC代码:

#include <bits/stdc++.h>

using namespace std;
typedef long long ll;
const int maxx=1e5+10;

int main()
{
    int T;
    int n,m;
    ll vc[maxx];
    ll add[maxx];
    cin>>T;
    while(T--)
    {
        memset(vc,0,sizeof(vc));
        memset(add,0,sizeof(add));
        cin>>n>>m;
        for(int a=1;a<=n;a++)cin>>vc[a];
        ll i,j;
        for(int a=1;a<=m;a++)
        {
            cin>>i>>j;
            add[i]+=j;
        }
        ll sum=0;
        for(int a=1;a<=n;a++)
        {
            sum+=add[a];
            if(sum>=vc[a])
            {
                cout<<vc[a]<<" ";
                sum-=vc[a];
            }
            else
            {
                cout<<sum<<" ";
                sum=0;
            }
        }
        cout<<endl;
    }
    return 0;
}

B: Prime Split

思路:预处理出4e4里的所有的素数,对于每一个n,枚举两个素数,判断第三个是不是素数即可(三个素数从大到小排,避免重复)。

AC代码:

#include <bits/stdc++.h>

using namespace std;
typedef long long ll;
const ll maxn=4e4+10;
ll prime[maxn];      //就是个素数表
bool sf[maxn];
ll num=0;      //判断这个数是不是素数,sf[i]中的i是从1到maxn的数
void sushu()
{         //核心 欧拉筛代码
           //num 用来记筛到第几个质数
    memset(sf,true,sizeof(sf));
    sf[1] = false;
    sf[0] = false;  //1 0 特判
    for(int i = 2;i <= maxn; i ++)
    {          //外层枚举1~maxn
        if(sf[i]) prime[++num] = i;      //如果是质数就加入素数表
        for(int j = 1;j <= num;j ++)
        {       //内层枚举num以内的质数
            if(i * prime[j] > maxn) break; //筛完结束
            sf[i * prime[j]] = false;      //筛掉...
            if(i % prime[j] == 0) break;   //避免重复筛
        }
    }
}
int erfen(int x)
{
    int st=0,len=num+1;
    while(len-st!=1)
    {
        int mid=(st+len)/2;
        if(prime[mid]>x)len=mid;
        else st=st=mid;
    }
    return st;
}
int main()
{
	int T;
	int n;
	int k,pos;
	int ans=0;
	sushu();
	cin>>T;
	while(T--)
    {
        cin>>n;
        ans=0;
        pos=erfen(n)+1;
        for(int i=1;i<=pos;i++)
            for(int j=i;j<=pos;j++)
            {
                k=n-prime[i]-prime[j];
                if(k<=0||k<prime[j])continue;
                else
                {
                    if(sf[k])
                        ans++;
                }
            }
        cout<<ans<<endl;
    }
	return 0;
}

C: connnect

思路:只需要建立3(n-1)条边即可,x,y,z分别排序相邻的两个点建一条边,跑一边最小生成树就行。

AC代码:

#include <bits/stdc++.h>

using namespace std;
typedef long long ll;
const ll maxx=2e5+10;
struct node
{
    ll from,to;
    ll val;
}edge[maxx*3];
struct Node
{
    ll x,y,z;
    ll idex;
}poll[maxx];
bool cmp1(Node a,Node b){return a.x<b.x;}
bool cmp2(Node a,Node b){return a.y<b.y;}
bool cmp3(Node a,Node b){return a.z<b.z;}
bool cmp(node a,node b){return a.val<b.val;}
ll Father[maxx];
ll Find(ll x)
{
    if(Father[x]==x)return x;
    else return Father[x]=Find(Father[x]);
}
ll unite(ll x,ll y)
{
    ll a=Find(x);
    ll b=Find(y);
    if(a!=b)
    {
        Father[a]=b;
        return 1;
    }
    else return 0;
}
int main()
{
    ll n;
    ll d=0;
    cin>>n;
    for(ll a=1;a<=n;a++)Father[a]=a;
    for(int a=1;a<=n;a++)
    {
        cin>>poll[a].x>>poll[a].y>>poll[a].z;
        poll[a].idex=a;
    }
    sort(poll+1,poll+1+n,cmp1);
    for(ll a=1;a<n;a++)
    {
        ++d;
        edge[d].from=poll[a].idex;
        edge[d].to=poll[a+1].idex;
        edge[d].val=abs(poll[a].x-poll[a+1].x);
    }
    sort(poll+1,poll+1+n,cmp2);
    for(ll a=1;a<n;a++)
    {
        ++d;
        edge[d].from=poll[a].idex;
        edge[d].to=poll[a+1].idex;
        edge[d].val=abs(poll[a].y-poll[a+1].y);
    }
    sort(poll+1,poll+1+n,cmp3);
    for(ll a=1;a<n;a++)
    {
        ++d;
        edge[d].from=poll[a].idex;
        edge[d].to=poll[a+1].idex;
        edge[d].val=abs(poll[a].z-poll[a+1].z);
    }
    sort(edge+1,edge+1+d,cmp);
    ll ans=0,cou=0;
    for(ll a=1;a<=d;a++)
    {
        if(unite(edge[a].from,edge[a].to))
        {
            ans+=edge[a].val;
            cou++;
        }
        if(cou==n-1)break;
    }
    cout<<ans<<endl;
	return 0;
}

D: K-nary

思路:数位dp,dp[i][j]表示有i位数,最后一位为j,dp[i][j]=求和dp[i-1][k],( abs( k ) > c )。

AC代码:

#include <bits/stdc++.h>

using namespace std;
typedef long long ll;
const ll maxx=1e3+10;
const ll MOD=1e9+7;
ll dp[maxx][maxx];
ll sum1;
ll sum2;
int n,k,c;
int main()
{
    int T;
    cin>>T;
    while(T--)
    {
        memset(dp,0,sizeof(dp));
        sum1=sum2=0;
        cin>>n>>k>>c;
        k--;
        ll sum=0;
        int t=0;
        for(int a=0;a<=k;a++)dp[1][a]=1,sum1+=dp[1][a];
        for(int i=2;i<=n;i++)
        {
            sum=0;
            if(i==n)t=1;
            for(int j=t;j<=k;j++)
            {
                sum2=0;
                for(int p=max(0,j-c);p<=min(j+c,k);p++)
                    sum2+=dp[i-1][p];
                dp[i][j]=(sum1-sum2)%MOD;
                sum+=dp[i][j];
            }
            sum1=sum;
        }
        ll ans=0;
        for(int a=0;a<=k;a++)
            ans=(ans+dp[n][a])%MOD;
        cout<<ans<<endl;
    }
	return 0;
}

E: Number

思路:用dp的思想求x,dp[i]表示i可以表示最大x,dp[i]=max(dp[i],dp[j]*dp[i-j]),求出x后用欧几里得求逆元(费马小定理x要为质数)。

AC代码:

#include <bits/stdc++.h>

using namespace std;
typedef long long ll;
const ll maxx=1e5+10;
ll dp[60];
ll exgcd(ll a,ll b,ll &x,ll &y)
{
    ll d=a;
    if(b!=0)
    {
        d=exgcd(b,a%b,y,x);
        y-=a/b*x;
    }
    else
    {
        x=1;
        y=0;
    }
    return d;
}
ll inverse(ll a,ll m)
{
    ll x,y;
    exgcd(a,m,x,y);
    return (x%m+m)%m;
}
int main()
{
	int n;
	cin>>n;
    dp[1]=1;
    dp[2]=2;
    dp[3]=3;
    dp[4]=4;
	for(int i=5;i<=n;i++)
    {
        dp[i]=i;
        for(int j=1;j<i;j++)
            dp[i]=max(dp[i],dp[j]*dp[i-j]);
    }
    ll x=dp[n];
	cout<<inverse(n,x)<<endl;;
	return 0;
}

F: 操作数

思路:线段树的区间求和,每个点只要操作次数为奇数则为1,否则为0

AC代码:

#include <bits/stdc++.h>

using namespace std;
typedef long long ll;
const long long INF=4e5+10;
typedef long long ll;
struct gg
{
    int left;
    int right;
    long long lazy;
    int getm(){return (left+right)/2;}
}tree[INF];
void pushdown(int i)
{
    if(tree[i].lazy)
    {
        tree[i<<1].lazy+=tree[i].lazy;
        tree[i<<1|1].lazy+=tree[i].lazy;
        tree[i].lazy=0;
    }
}
void builttree(int l,int r,int i)
{
    tree[i].left=l;
    tree[i].right=r;
    tree[i].lazy=0;
    if(l==r)return;
    int mid=(l+r)/2;
    builttree(l,mid,i<<1);
    builttree(mid+1,r,i<<1|1);
}
void updatetree(int l,int r,ll c,int i)
{
    int mid=tree[i].getm();
    if(l<=tree[i].left&&tree[i].right<=r)
    {
        tree[i].lazy+=c;
        return ;
    }
    pushdown(i);
    if(mid>=l)updatetree(l,r,c,i<<1);
    if(mid<r)updatetree(l,r,c,i<<1|1);
}
ll query(int idex,int i)
{
    int mid=tree[i].getm();
    if(tree[i].left==tree[i].right)
    {
        if(tree[i].lazy%2==0)return 0;
        else return 1;
    }
    pushdown(i);
    if(mid>=idex)return query(idex,i<<1);
    if(mid<idex)return query(idex,i<<1|1);
}
int main()
{
    int n,m;
    int po,l,r,x;
    cin>>n>>m;
    builttree(1,n,1);
    while(m--)
    {
        cin>>po;
        if(po==1)
        {
            cin>>l>>r;
            updatetree(l,r,1,1);
        }
        else
        {
            cin>>x;
            cout<<query(x,1)<<endl;
        }
    }
    return 0;
}

G: 聚会

思路:预处理出C几几(有除法,注意要求逆元),然后乘上2的几次方减2,累加总数即可。

AC代码:

#include <bits/stdc++.h>

using namespace std;
typedef long long ll;
const ll maxx=1e5+10;
const ll MOD=1e9+7;
ll mypow(ll a,ll b)
{
    ll res=1;
    while(b)
    {
        if(b&1)res=(res*a)%MOD;
        a=(a*a)%MOD;
        b>>=1;
    }
    return res;
}
int main()
{
	ll n;
	ll number[maxx];
	ll ans=0;
	cin>>n;
	number[2]=((n*(n-1))%MOD*mypow(2,MOD-2))%MOD;
	for(int i=3;i<=n;i++)
        number[i]=(number[i-1]*((n-i+1)*mypow(i,MOD-2)%MOD)%MOD)%MOD;
    for(int i=2;i<=n;i++)
        ans=(ans+(number[i]*(mypow(2,i)-2))%MOD)%MOD;
    cout<<ans<<endl;
	return 0;
}

H: 地图

思路:求三次bfs,第一次为第一个图,第二次为第二个图,第三位两个的合起来的图,求每次的步数,每次相等且可以到达即为YES,否则为NO。

AC代码:

#include <bits/stdc++.h>
 
using namespace std;
typedef long long ll;
int han[4]={0,1,0,-1};
int lie[4]={1,0,-1,0};
int mapp[510][510];
int n,m;
int step[510][510];
int bfs(char vis[510][510])
{
    queue<pair<int,int> >str;
    memset(mapp,0,sizeof(mapp));
    str.push(make_pair(1,1));
    if(mapp[1][1]==1){return -1;}
    if(n==1&&m==1&&vis[n][m]!='#')return 1;
    mapp[1][1]=1;
    step[1][1]=1;
    while(str.size())
    {
        pair<int,int>po=str.front();
        str.pop();
        for(int a=0;a<4;a++)
        {
            int nowh=po.first+han[a];
            int nowl=po.second+lie[a];
            if(nowh>=1&&nowh<=n&&nowl>=1&&nowl<=m&&mapp[nowh][nowl]==0&&vis[nowh][nowl]!='#')
            {
                mapp[nowh][nowl]=1;
                step[nowh][nowl]=step[po.first][po.second]+1;
                if(nowh==n&&nowl==m)return step[nowh][nowl];
                str.push(make_pair(nowh,nowl));
            }
        }
    }
    return -1;
}
 
int main()
{
	cin>>n>>m;
	char c[3][510][510];
	for(int a=1;a<=n;a++)
        for(int b=1;b<=m;b++)
            cin>>c[1][a][b];
    for(int a=1;a<=n;a++)
        for(int b=1;b<=m;b++)
            cin>>c[2][a][b];
    int flag=1;
    int ans1=bfs(c[1]),ans2=bfs(c[2]);
    if(ans1!=ans2||(ans1==ans2&&ans1==-1))flag=0;
    for(int a=1;a<=n;a++)
        for(int b=1;b<=m;b++)
        {
            if(c[1][a][b]!='#'&&c[2][a][b]=='#')
                c[1][a][b]='#';
        }
    int ans3=bfs(c[1]);
    if(ans1!=ans3)flag=0;
    /*cout<<ans1<<" "<<ans2<<" "<<ans3<<endl;*/
    if(flag)cout<<"YES"<<endl;
    else cout<<"NO"<<endl;
	return 0;
}

I: 我是签到题

思路:从前往后遍历到(n-1)/2,遇到ai!=a n-i-1都改成最小的那个。

AC代码:

#include <bits/stdc++.h>

using namespace std;
typedef long long ll;
const int maxx=2e5+10;

int main()
{
    string s;
    cin>>s;
    int n=s.length();
    for(int a=0;a<=(s.length()-1)/2;a++)
    {
        if(s[a]!=s[n-a-1])
        {
            if(s[a]<s[n-a-1])s[n-a-1]=s[a];
            else s[a]=s[n-a-1];
        }
    }
    cout<<s<<endl;
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值