A. Divide it!
分析:2,3,5互质,直接暴力即可。
#include "bits/stdc++.h"
using namespace std;
int main(){
int q;
cin>>q;
while(q--){
long long n;
cin>>n;
int ans= 0;
while(n%5==0){
n=n/5*4;
ans++;
}
while (n%3==0){
n=n/3*2;
ans++;
}
while(n%2==0){
n=n/2;
ans++;
}
if(n==1)cout<<ans<<endl;
else puts("-1");
}
}
B. Merge it!
分析:直接记录mod3=1,2,0的个数,然后配对就可以了。
#include "bits/stdc++.h"
using namespace std;
int main(){
int t;
cin>>t;
while (t--){
int n;
cin>>n;
int a1,a2,a3;
a1=a2=a3=0;
int x;
for (int i = 0; i < n; ++i) {
scanf("%d",&x);
if(x%3==0)a3++;
if(x%3==1)a1++;
if(x%3==2)a2++;
}
if(a1>a2)swap(a1,a2);
a3+=a1;
a3+=(a2-a1)/3;
cout<<a3<<endl;
}
}
C. Lose it!
分析:直接线性跑一遍记录个数就可以了。最后n-6*num
#include "bits/stdc++.h"
using namespace std;
int a[500004];
int main() {
int n;
cin >> n;
int a4, a8, a15, a16, a23, a42;
a4 = a8 = a15 = a16 = a23 = a42 = 0;
for (int i = 0; i < n; ++i) {
scanf("%d", &a[i]);
}
for (int i = 0; i < n; ++i) {
if(a[i]==4){
a4++;
}
if(a[i]==8){
if(a4)a4--,a8++;
}
if(a[i]==15){
if(a8)a8--,a15++;
}
if(a[i]==16){
if(a15)a15--,a16++;
}
if(a[i]==23){
if(a16)a16--,a23++;
}
if(a[i]==42){
if(a23)a23--,a42++;
}
}
printf("%d\n",n-a42*6);
}
D. Recover it!
分析:质数只能引进比自己大的质数,非质数可以引进比自己小的质数或非质数,那么最大的非质数一定是原数组的。
按照这个思路从大的非质数开始找,然后再从小的质数找,用multiset维护一下就可以了。
#include "bits/stdc++.h"
using namespace std;
bool vis[2750132];
int prim[200004];
int cnt ;
int to[200004];
void init(){
cnt = 1;
for (int i = 2; i <= 2750131 ; ++i) {
if(!vis[i])prim[cnt++]=i;
for (int j = 1; j <= cnt && i* prim[j]<=2750131 ; ++j) {
vis[i*prim[j]]=1;
if(i%prim[j]==0)break;
}
}
for (int i = 2; i <= 200000; ++i) {
if(!vis[i])to[i]=prim[i];
else {
for (int j = 1; j <=cnt ; ++j) {
if(i%prim[j]==0){
to[i]=i/prim[j];
break;
}
}
}
}
}
int a[200004];
int b[400004];
bool viss[400004];
int pos;
int main() {
int n;
cin >> n;
pos=1;
init();multiset<int>s;
for (int i = 1; i <= 2*n; ++i) {
scanf("%d",&b[i]);
s.insert(b[i]);
}
sort(b+1,b+1+n+n);
for (int i = n*2; i >= 1; --i) {
if(vis[b[i]] && s.count(b[i])){
a[pos++]=b[i];
s.erase(s.find(b[i]));
s.erase(s.find(to[b[i]]));
}
}
while(!s.empty()){
auto it = s.begin();
int x=*it;
a[pos++]=x;
s.erase(s.find(to[x]));
s.erase(s.begin());
}
for (int i = 1; i <= n; ++i) {
printf("%d ",a[i]);
}
}
E. Cover it!
分析:建图然后枚举点染色,只染相邻的点,染过的点直接跳过。然后判断一下个数输出染色的点或者未染色点。
#include "bits/stdc++.h"
using namespace std;
vector<int>v[200004];
bool vis[200004];
void to(int u){
for (int i = 0; i < v[u].size(); ++i) {
vis[v[u][i]]=1;
}
}
int main() {
int t;
cin>>t;
while(t--){
int n,m;
scanf("%d%d",&n,&m);
int x,y;
for (int i = 0; i <= n; ++i) {
v[i].clear();
}
memset(vis,0, sizeof(vis));
for (int i = 0; i < m; ++i) {
scanf("%d%d",&x,&y);
v[x].push_back(y);
v[y].push_back(x);
}
int ans=0;
for (int i = 1; i <= n; ++i) {
if(!vis[i]){
ans++;
to(i);
}
}
if(ans<=n/2){
printf("%d\n",ans);
for (int i = 1; i <= n; ++i) {
if(!vis[i])printf("%d ",i);
}
}
else {
printf("%d\n",n-ans);
for (int i = 1; i <= n; ++i) {
if(vis[i])printf("%d ",i);
}
}
puts("");
}
}
F. Destroy it!
分析:用dp[i][j]表示第i个回合,已经打出了x张牌且x%10==j,每次打牌的情况只有4种:0,1,2,3,找出每种对应状态的最大的几张牌,递推状态就可以了。
#include "bits/stdc++.h"
using namespace std;
vector<long long> v[200004][4];
long long dp[200004][10];
bool cmp(long long a, long long b) {
return a > b;
}
int main() {
int n;
cin >> n;
for (int i = 1; i <= n; ++i) {
int k;
scanf("%d", &k);
long long c, d;
for (int j = 0; j < k; ++j) {
scanf("%lld%lld", &c, &d);
v[i][c].push_back(d);
}
for (int j = 1; j <= 3; ++j) {
sort(v[i][j].begin(), v[i][j].end(), cmp);
}
}
memset(dp, -1, sizeof(dp));
dp[0][0] = 0;
for (int i = 1; i <= n; ++i) {
int X = v[i][1].size() + v[i][2].size() + v[i][3].size();
for (int j = 1; j <= 3; ++j) {
if (X < j)break;
long long a[3] = {0};
if (j == 1) {
if (v[i][1].size())
a[0] = max(a[0], v[i][1][0]);
if (v[i][2].size())
a[0] = max(a[0], v[i][2][0]);
if (v[i][3].size())
a[0] = max(a[0], v[i][3][0]);
} else if (j == 2) {
if (!(v[i][1].size() > 0 && v[i][1].size() + v[i][2].size() > 1))continue;
if (v[i][1].size())
a[0] = max(a[0], v[i][1][0]);
else continue;
if (v[i][2].size())
a[1] = max(a[1], v[i][2][0]);
if (v[i][1].size() > 1)
a[1] = max(a[1], v[i][1][1]);
} else if (j == 3) {
if (v[i][1].size() < 3)continue;
for (int k = 0; k < 3; ++k) {
a[k] = v[i][1][k];
}
}
sort(a, a + j);
for (int k = 0; k < 10; ++k)dp[i][k]=max(dp[i][k],dp[i-1][k]);
for (int k = 0; k < 10; ++k) {
if (dp[i - 1][k] == -1)continue;
long long sum = 0;
if (k + j >= 10)for (int l = 0; l < j; ++l)sum += (l == j - 1 ? 2LL * a[l] : a[l]);
else for (int l = 0; l < j; ++l)sum += a[l];
dp[i][(k + j) % 10] = max(dp[i][(k + j) % 10], dp[i - 1][k] + sum);
}
}
}
long long ans = 0;
for (int i = 0; i < 10; ++i) {
ans = max(ans, dp[n][i]);
}
cout << ans << endl;
}