8_15 小测

第1题 Coprime

image

输入格式

image

输出格式

image

思路:

我们知道互质的两个数的因数除1外都不相同,多个数也一样。所以我们可以枚举因数的倍数,在用数组计数计算有多少个数的因数是这个因数。如果个数大1那就和两两互质无关,如果个数等于n那就和两两集合无关了。

代码:

#include<bits/stdc++.h>
using namespace std;
int n,a[1000005],c[1000005];
int main(){
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	{
		scanf("%d",&a[i]);
		c[a[i]]++;//数组计数
	}
	bool d=1,f=1;
	for(int i=2;i<=1000000;i++)
	{
		int t=0;
		for(int j=i;j<=1000000;j=j+i)
		{
			t=t+c[j];//累加个数
		}
		if(t>1)d=0;//和两两互质无关
		if(t==n)f=0;//和集合互质无关
	}
	if(d)printf("pairwise coprime");
	else if(f)printf("setwise coprime");
	else printf("not coprime");
	
	return 0; 
}

第2题 旅游

image

输入格式

image

输出格式

image

思路:

当看到城市之间有n-1条道路的时候我们可以想到树,因为树上s~t的路径一定,用LCA算出即可。但有k个传送门,于是我们可以求出离s最近的传送门距离和离t最近的传送门距离的和与s~t的路径长度取个最小即答案。

代码:

#include<bits/stdc++.h>
using namespace std;
long long n,T,m,q,op[2000005],num,f[2000005][25],d[2000005];
vector<int>a[2000005];
inline void solve()
{
    queue<long long>q;
    for(int i=1;i<=m;i++)
	{
		int x;
        cin>>x;
        q.push(x);
        op[x]=0;
    }
    while(!q.empty())
	{
        int u=q.front();
        q.pop();
    	for(int i=0;i<a[u].size();i++)
		{
            int v=a[u][i];
            if(op[v]!=-1)continue;
            op[v]=op[u]+1;
            q.push(v);
        }
    }
}
void dfs(int x,int fa)
{
    f[x][0]=fa;
    d[x]=d[fa]+1;
    for(int i=1;i<=20&&f[f[x][i-1]][i-1]; i++)
	{
        f[x][i]=f[f[x][i-1]][i-1];
    }
    for(int i=0;i<a[x].size();i++)
	{
        if(a[x][i]!=fa)
		{
            dfs(a[x][i], x);
        }
    }
}
int lca(int x, int y)
{
    if(d[x]<d[y]) swap(x, y);
    for(int i=20;i>=0;i--)
	{
        if(d[f[x][i]] >= d[y])
		{
            x=f[x][i];
        }
    }
    if(x==y)return x;
    for(int i=20;i>=0; i--)
	{
        if(f[x][i]!=f[y][i])
		{
            x=f[x][i];
            y=f[y][i];
        }
    }
    return f[x][0];
}
int main(){
    cin>>n>>m>>q;
    for(int i=1;i<=n;i++)
	{
        op[i]=-1;
    }
    for(int i=1;i<n;i++)
	{
		int u,v;
        cin>>u>>v;
        a[u].push_back(v);
        a[v].push_back(u);
    }
    dfs(1, 0);
    solve();
    while(q--)
	{
        int x,y;
        cin>>x>>y;
        int LCA=lca(x, y);
        cout<<min(d[x]-d[LCA]+d[y]-d[LCA],(op[x]==-1 || op[y]==-1)?LLONG_MAX:op[x]+op[y])<<"\n";
    }
    
    return 0;
}

第3题 考试

image

输入格式

image

输出格式

image

思路:

观察题目我们可以发现如果B<A时加B肯定更好,所以我们可以枚举最后的课程的天数,算出将最后的课程的天数压倒枚举的数最小的不愉快度的最小值就是答案。

代码:

#include<bits/stdc++.h>
using namespace std;
unsigned long long a,b,A,B,C,n,m,bb[100005],aa[100005],aaa,bbb;
int main(){
	scanf("%llu%llu%llu",&A,&B,&C);
	scanf("%llu%llu",&n,&m);
	for(int i=1;i<=n;i++)
	{
		scanf("%llu",&a);
		aa[a]++;
		aaa+=a;
	}
	for(int i=1;i<=m;i++)
	{
		scanf("%llu",&b);
		bb[b]++;
		bbb+=b;
	}
	unsigned long long y=LLONG_MAX,p1=0,p2=0,s1=bbb,s2=m,s3=aaa,s4=n;
	for(int i=100000;i>=1;i--)//枚举最后的课程的天数
	{
		p1+=1ull*i*bb[i];
        p2+=bb[i];
        s1-=1ull*i*bb[i];
        s2-=bb[i];
        s3-=1ull*i*aa[i];
        s4-=aa[i];
        if(p2==0)continue;
        unsigned long long t=0;
        if(A<B)
        {
            t=t+min(p1-p2*i,s2*i-s1)*A;
            if(p1-p2*i-min(p1-p2*i,s2*i-s1))t=t+(p1-p2*i-min(p1-p2*i,s2*i-s1))*B;
		}
		else
		{
            t=t+(p1-p2*i)*B;
		}
		t=t+(s4*i-s3)*C;
		y=min(y,t);
	}
	printf("%llu",y);
	
    return 0;
}
posted @ 2025-09-22 17:12  PLJZ  阅读(8)  评论(0)    收藏  举报