8.26考总

炸了

T1

质数筛+预处理处理出每个数的答案

#include<bits/stdc++.h>
#define int long long
#define endl "\n"
using namespace std;
const int maxn=4e6+5,mod=1e9+7,inf=1e18;
int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0' && ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
void write(int x){if(x<0){putchar('-'),x=-x;}if(x>9){write(x/10);}putchar(x%10+'0');return;}
int fpow(int a,int b,int p){if(b==0){return 1;}int res=fpow(a,b/2,p)%p;if(b%2==1){return((res*res)%p*a)%p;}else{return(res*res)%p;}}
int t,n;
bool prime[maxn];
int ans[maxn];
void init(){
	for(int i=2;i<=maxn-5;i++){
		if(prime[i]==0){
			for(int j=i+i;j<=maxn-5;j+=i){
				prime[j]=1;
				
			}
		}
		for(int j=i+i;j<=maxn-5;j+=i){
			ans[j]=i;
			
		}
	}
}
void solve(){
	cin>>n;
	if(prime[n]==0){
		cout<<1<<endl;
	}
	else{
		cout<<ans[n]<<endl;
	}
}
signed main(){
	init();
	cin>>t;
	while(t--){
		solve();
	}
	return 0;
}

T2

观察可发现,其实每一对都是两个质数的倍数,我们求出最大的质数的最大倍数,预处理出来即可

#include<bits/stdc++.h>
#define int long long
#define endl "\n"
using namespace std;
const int maxn=2e4+5,mod=99824353,inf=1e18;
int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0' && ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
void write(int x){if(x<0){putchar('-'),x=-x;}if(x>9){write(x/10);}putchar(x%10+'0');return;}
int fpow(int a,int b,int p){if(b==0){return 1;}int res=fpow(a,b/2,p)%p;if(b%2==1){return((res*res)%p*a)%p;}else{return(res*res)%p;}}
int t,n;
bool prime[maxn];
int num[maxn];
int ans,dp[maxn];
int cnt=0;
void init(){
	prime[1]=prime[0]=1;
	for(int i=2;i<=maxn;i++){
		if(prime[i]==0){
			for(int j=i+i;j<=maxn;j+=i){
				prime[j]=1;
			}
		}
	}
}
void solve(){
	cin>>n;
	ans+=dp[n];
	ans%=mod;
}
signed main(){
	init();
	for(int i=1;i<=10000;i++){
		if(prime[i]==0){
			num[cnt++]=i;
		}
	}
	cnt--;
	for(int i=1;i<=10000;i++){
		int sum=0;
		for(int j=0;j<=cnt&&num[j]<=i;j++){
			int x=i/num[j];
			sum+=x*j;
			sum%=mod;
		}
		sum*=2;
		sum%=mod;
		dp[i]=sum;
	}
	cin>>t;
	while(t--){
		solve();
	}
	cout<<ans;
	return 0;
}

T3

考虑DP

状态:dp[i]表示前i个字符的最大答案

答案:dp[n]

方程:dp[i]=dp[i-1]
dp[i]=max(dp[i],dp[i-4]+a)
dp[i]=max(dp[i],dp[i-6]+b)
dp[i]=max(dp[i],dp[i-10]+c)

边界:dp[1-3]=0

#include<bits/stdc++.h>
#define int long long
#define endl "\n"
using namespace std;
const int maxn=1e6+5,mod=1e9+7,inf=1e18;
int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0' && ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
void write(int x){if(x<0){putchar('-'),x=-x;}if(x>9){write(x/10);}putchar(x%10+'0');return;}
int fpow(int a,int b,int p){if(b==0){return 1;}int res=fpow(a,b/2,p)%p;if(b%2==1){return((res*res)%p*a)%p;}else{return(res*res)%p;}}
int n,a,b,c;
string s;
int dp[maxn];
bool check(int x,string s1){
	int len=s1.size();
	int cnt=0;
	if(x<len){
		return 0;
	}
	for(int i=x-len+1;i<=x;i++){
		if(s[i]!=s1[cnt++]){
			return 0;
		}
	}
	return 1;
}
void solve(){
	cin>>n>>a>>b>>c;
	cin>>s;
	s=' '+s;
	string s1="acwa",s2="acwaac",s3="acwaacwaac";
	for(int i=4;i<=n;i++){
		dp[i]=dp[i-1];
		if(check(i,s1)){
			dp[i]=max(dp[i],dp[i-4]+a);
		}
		if(check(i,s2)){
			dp[i]=max(dp[i],dp[i-6]+b);
		}
		if(check(i,s3)){
			dp[i]=max(dp[i],dp[i-10]+c);
		}
	}
	cout<<dp[n]<<endl;
}
signed main(){
	solve();
	return 0;
}

T4

首先不能最大生成树,因为可以有环

我们判断一下连通块,在一个连通块中,一定有n条边给我们选取

所以我们判断一下连通块的数量和边的数量,再按最小生成树的贪心选取即可

#include<bits/stdc++.h>
#define int long long
#define endl "\n"
using namespace std;
const int maxn=1e6+5,mod=1e9+7,inf=1e18;
int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0' && ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
void write(int x){if(x<0){putchar('-'),x=-x;}if(x>9){write(x/10);}putchar(x%10+'0');return;}
int fpow(int a,int b,int p){if(b==0){return 1;}int res=fpow(a,b/2,p)%p;if(b%2==1){return((res*res)%p*a)%p;}else{return(res*res)%p;}}
int n,t,m;
string s;
int fa[maxn];
int edge[maxn],node[maxn];
struct Node{
	int u,v,w;
}a[maxn];
int find(int x){
	if(fa[x]==x){
		return x;
	}
	return fa[x]=find(fa[x]);
}
bool cmp(Node x,Node y){
	return x.w>y.w;
}
void solve(){
	cin>>n>>m;
	for(int i=1;i<=n;i++){
		fa[i]=i;
		edge[i]=0;
		node[i]=1;
	}
	for(int i=1;i<=m;i++){
		cin>>a[i].u>>a[i].v>>a[i].w;
	}
	sort(a+1,a+m+1,cmp);
	int ans=0;
	for(int i=1;i<=m;i++){
		int u=find(a[i].u);
		int v=find(a[i].v);
		if(u==v){//在同一个块里面
			if(edge[u]<node[u]){//边要够
				edge[u]++;
				ans+=a[i].w;
			}
		}
		else{
			if(edge[u]<node[u]||edge[v]<node[v]){//边的数量必须足够
				fa[u]=v;//合并连通块
				edge[v]+=edge[u];
				node[v]+=node[u];
				ans+=a[i].w;
				edge[v]++;
			}
		}
	}
	cout<<ans<<endl;
}
signed main(){
	cin>>t;
	while(t--){
		solve();
	}
	
	return 0;
}

posted @ 2025-08-26 21:00  KK_SpongeBob  阅读(8)  评论(0)    收藏  举报