题目链接: https://codeforces.com/contest/1176
题目:
D. Recover it!
题面:
思路: 线性筛出199999个质数,顺便储存每个合数的最大因子,然后2750131开始倒推,大的质数肯定是某个小的数映射而来,大的合数可以求出最大因子数
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e5+5;
int a[N];int b[2750135];
int prime[N];
bool vis[2750135];
int di[2750135];
int cntt=0;
void init()
{
for(int i=2;i<=2750131;i++)
{
if(!vis[i])
prime[++cntt]=i;
for(int j=1;j<=cntt&&prime[j]*i<=2750131;j++)
{
di[i*prime[j]]=max(i,di[i*prime[j]]);
vis[prime[j]*i]=1;
if(i%prime[j]==0) break;
}
}
}
int main()
{
init();
int n;
int maxx=0;
scanf("%d",&n);
for(int i=1;i<=2*n;i++)
{
int num;
scanf("%d",&num);
b[num]++;
if(num>maxx)
maxx=num;
}
int cnt=0;
for(int i=maxx;i>1;i--)
{
while(b[i])
{
b[i]--;
if(vis[i])
{
a[++cnt]=i;
b[di[i]]--;
}
else
{
int tmp=lower_bound(prime+1,prime+cntt+1,i)-prime;
a[++cnt]=tmp;
b[tmp]--;
}
}
}
for(int i=1;i<=cnt;i++)
printf("%d ",a[i]);
puts("");
return 0;
}
**E - Cover it! **
题意: 给你一个无向图,问你最多选出n/2个点,使剩下的点至少连接着某个已选的点
思路: 01染色经典问题,ans=min ( cnt[ 0 ],cnt[ 1 ] )
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e5+5;
vector<int>G[N];
int vis[N];
void dfs(int u,int x)
{
vis[u]=x;
for(int i=0;i<G[u].size();i++)
{
int v=G[u][i];
if(vis[v]==-1)
dfs(v,x^1);
}
}
int main()
{
int T;
scanf("%d",&T);
int n=0,m;
while(T--)
{
for(int i=1;i<=n;i++)
G[i].clear();
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
{
int u,v;
scanf("%d%d",&u,&v);
G[u].push_back(v);
G[v].push_back(u);
}
for(int i=1;i<=n;i++)
{
vis[i]=-1;
}
dfs(1,0);
int cnt1=0,cnt0=0;
for(int i=1;i<=n;i++)
{
if(vis[i])
cnt1++;
else
cnt0++;
}
if(cnt0>cnt1)
{
printf("%d\n",cnt1);
for(int i=1;i<=n;i++)
{
if(vis[i]==1)
printf("%d ",i);
}
}
else
{
printf("%d\n",cnt0);
for(int i=1;i<=n;i++)
{
if(vis[i]==0)
printf("%d ",i);
}
}
puts("");
}
return 0;
}
F. Destroy it!
题意: 有n轮打击,每一轮打击使用总体力不超过3,且每整十次,技能伤害翻倍,问打出最大伤害是多少
思路: DP题,其实每一轮我们需要最多需要考虑5种技能,3种最大伤害且体力为1,1种伤害且最大体力为2,1种伤害最大且体力为3,因为我们只会优先从这五张选取,其他牌扔掉,所以我们可以先预处理出来
接着对每轮的选取方式进行DP,
选三张 三张1 ;
选两张 两张1 ; 一张2一张1
选一张 一张1 ; 一张2 ; 一张3
注意考虑若在第十应该是最大的翻倍
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e5+5;
struct node
{
int c1,c2,c3;
ll x1[4],x2,x3;
}a[N];
bool cmp(ll x,ll y)
{
return x>y;
}
ll dp[10],temp[10];
int main()
{
int T;
scanf("%d",&T);
int n;
int t=1;
while(T--)
{
scanf("%d",&n);
vector<ll>tmp;
tmp.clear();
for(int i=1;i<=n;i++)
{
ll c,d;
scanf("%lld%lld",&c,&d);
if(c==1)
{
tmp.push_back(d);
a[t].c1++;
}
else if(c==2)
{
a[t].c2++;
a[t].x2=max(a[t].x2,d);
}
else
{
a[t].c3++;
a[t].x3=max(a[t].x3,d);
}
}
sort(tmp.begin(),tmp.end(),cmp);
for(int i=0;i<3&&i<a[t].c1;i++)
{
//cout<<tmp[i]<<endl;
a[t].x1[i+1]=tmp[i];
}
t++;
}
memset(dp,-1,sizeof dp);
dp[0]=0;
//cout<<t<<endl;
for(int i=1;i<t;i++)
{
ll *x1=a[i].x1,x2=a[i].x2,x3=a[i].x3;
//cout<<x1[0]<<endl;
int c1=a[i].c1,c2=a[i].c2,c3=a[i].c3;
memcpy(temp,dp,sizeof dp);
for(int j=0;j<10;j++)
{
if(temp[j]==-1)
continue;
//选1张
if(j<9)
{
if(c1)
dp[j+1]=max(dp[j+1],temp[j]+x1[1]);
if(c2)
dp[j+1]=max(dp[j+1],temp[j]+x2);
if(c3)
dp[j+1]=max(dp[j+1],temp[j]+x3);
}
else
{
if(c1)
dp[0]=max(dp[0],temp[j]+2*x1[1]);
if(c2)
dp[0]=max(dp[0],temp[j]+2*x2);
if(c3)
dp[0]=max(dp[0],temp[j]+2*x3);
}
//选2张
if(j<8)
{
if(c1>=2)
dp[j+2]=max(dp[j+2],temp[j]+x1[1]+x1[2]);
if(c2&&c1)
dp[j+2]=max(dp[j+2],temp[j]+x2+x1[1]);
}
else
{
if(c1>=2)
dp[j-8]=max(dp[j-8],temp[j]+2*x1[1]+x1[2]);
if(c2&&c1)
{
ll maxx=max(x2,x1[1]);
dp[j-8]=max(dp[j-8],temp[j]+x2+x1[1]+maxx);
}
}
//选3张
if(j<7)
{
if(c1>=3)
{
dp[j+3]=max(dp[j+3],temp[j]+x1[1]+x1[2]+x1[3]);
}
}
else
{
if(c1>=3)
{
dp[j-7]=max(dp[j-7],temp[j]+x1[1]*2+x1[2]+x1[3]);
}
}
}
}
ll ans=0;
for(int i=0;i<=9;i++)
{
ans=max(ans,dp[i]);
}
printf("%lld\n",ans);
return 0;
}