Codeforces Round #565 (Div. 3)
题意:满足下面的条件,输出替换后的最小的数,反之输出-1。
暴力
#include <bits/stdc++.h> #include <iostream> using namespace std; const int maxn=2e4+5; //int a[maxn][maxn]; #define ll long long int main(){ int n; cin>>n; while(n--){ ll m; cin>>m; int ans=0; while(m!=1){ ans++; if(m%2==0) m/=2; else if(m%3==0) m=m/3*2; else if(m%5==0) m=m/5*4; else { ans=-1; break; } } cout<<ans<<endl; } return 0; }
题意:通过合并一些数,使得能被3整除的最多个数是多少。
想的深入一点,会发现其实可以变成只包含1,2序列,将数组预处理%上3,找出能被3整除的,然后把得到的只包含1,2的序列合并成3就简单多了,加上这里合并出来的3就是答案了
#include <bits/stdc++.h> #include <iostream> using namespace std; const int maxn=2e4+5; int a[maxn]; #define ll long long //sync_with_stdio (false); int main(){ int n,m; cin>>n; while(n--){ cin>>m; int index=0; for(int i=0; i<m; i++){ int x=0; cin>>x; if(x%3!=0) a[index++]=x%3; } int ans=m-index; int y1=0,y2=0; for(int i=0; i<index; i++){ if(a[i]==1) y1++; else y2++; } if(y1>=y2){ ans+=(y2+(y1-y2)/3); } else ans+=(y1+(y2-y1)/3); cout<<ans<<endl; } return 0; }
题意:删除最少的元素,使的数组中的元素都是由下面的序列组成的,换句话说:该序列包含了n个该子序列
4,8,15,16,23,42
题目看错,反应过来,dp写错,不是42元素前面有4,8,15,16,23元素,而是要有这个序列,是顺序要求的 qwq
wa了的代码:
#include <bits/stdc++.h> #include <iostream> using namespace std; const int maxn=2e4+5; int a[50]; #define ll long long //sync_with_stdio (false); int main(){ memset(a,0,sizeof(a)); int n,m=600000; cin>>n; int ans=0; for(int i=0; i<n; i++){ float x; cin>>x; if(x/4==1) a[0]++; else if(x/8==1) a[1]++; else if(x/15==1) a[2]++; else if(x/16==1) a[3]++; else if(x/23==1) a[4]++; else if(x/42==1) a[5]++; if(x==42){ if(a[0]>0&&a[1]>0&&a[2]>0&&a[3]>0&&a[4]>0&&a[5]>0){ a[0]--,a[1]--,a[2]--,a[3]--,a[4]--,a[5]--; ans++; } } } ans=n-ans*6; cout<<ans<<endl; return 0; }
简单dp(ac)
#include <bits/stdc++.h> #include <iostream> using namespace std; const int maxn=2e4+5; int a[50]; map<int,int> mp; #define ll long long // int main(){ std::ios::sync_with_stdio (false); memset(a,0,sizeof(a)); mp[4]=0,mp[8]=1,mp[15]=2,mp[16]=3,mp[23]=4,mp[42]=5; int n,m=600000; cin>>n; int ans=0; for(int i=0; i<n; i++){ int x; cin>>x; int index=mp[x]; if(mp[x]==0||a[index-1]>a[index]) a[index]++; } //cout<<ans<<endl; ans=n-a[5]*6; cout<<ans<<endl; return 0; }
题意:删除一些点,不超过总数的一半,使剩下的点和至少和一个删除的点有一天边。
开始时,一句关键的画没看懂,把题目读偏了,看了一下别人的题解,有人说是二分图,其实不是的,只是做法有些类似,用dfs把相邻边染成不同颜色,但其实这里相邻点可以是相同颜色,只有当相邻点颜色不同时,才时二分图,其实这也是二分图的判定方法。
dfs时O(n),还有n组数据,时间复杂度时O(n*n);2秒,应该会T啊,是数据水了吗qwq
#include <bits/stdc++.h> #include <iostream> using namespace std; #define ll long long const int maxn=2e5+5; //int a[maxn],tmp[maxn]; pair<int,int> p; map<int,int> mp; //map<int,int> ::iterator it; //vector<pair<int,int> >::iterator its; vector<int> edge[maxn]; bool vis[maxn]; set<int> a,b; set<int> ::iterator it; void dfs(int u,int flag){ vis[u]=1; if(flag) a.insert(u); else b.insert(u); for(int i=0; i<edge[u].size(); ++i){ if(!vis[edge[u][i]]) { dfs(edge[u][i],!flag); } } } void init(int n){ a.clear(),b.clear(); for(int i=1; i<=n; ++i) edge[i].clear(),vis[i]=0; } int main(){ std::ios::sync_with_stdio (false); int q,n,m,u,v; cin>>q; while(q--){ cin>>n>>m; init(n); for(int i=0; i<m; ++i){ cin>>u>>v; edge[u].push_back(v),edge[v].push_back(u); } dfs(1,1); if(a.size()>b.size()){ cout<<b.size()<<"\n"; for(it=b.begin(); it!=b.end(); ++it) cout<<*it<<" "; cout<<"\n"; } else{ cout<<a.size()<<"\n"; for(it=a.begin(); it!=a.end(); ++it) cout<<*it<<" "; cout<<"\n"; } } return 0; }
题意:进行下面的操作,将的得到的a[n],b[n]数组混合,要你还原出a[n]数组
素数筛,求最大共因数,排一下序,从大到小扫一遍,如果是因数,找到其是第几个素数(map映射),加入a数组中,并将其从b中出去(我是用map处理的);如果不是因数,把它加入a,从b中删除其最大的因数(map处理)
注意:一定要处理那些b中不是a中的数
这里求最大公因数的 最快方法是能被整除的最小质数的那个数(有点虚)
#include <bits/stdc++.h> #include <iostream> using namespace std; #define ll long long const int maxn=4e5+5; //int a[maxn],tmp[maxn]; pair<int,int> p; map<int,int> mp; map<int,int> mpp; map<int,int> ::iterator it; //vector<pair<int,int> >::iterator its; //ll mod=1e9+7; struct edge{ ll v; ll du; }; int a[maxn]; bool cmp(int a,int b){ return a>b; } bool prime[2750131+5]; void getprime(){ int index=0; for(int i=2; i*i<2750131+5; ++i) if(!prime[i]) { for(int j=i*i; j<2750131+5; j+=i) prime[j]=1; } for(int i=2; i<=2750131; ++i) if(!prime[i]) mp[i]=++index; } ll mulit(ll base,ll k ,ll mod){ ll ans=1; while(k){ if(k%2) ans=base*ans%mod; base=base*base%mod; k>>=1; } return ans%mod; } ll sub(ll a, ll b, ll mod){ ll ans=a-b; if(ans<0) ans+=mod; return ans; } int main(){ std::ios::sync_with_stdio (false); int t,n,m,v,u; cin>>n; getprime(); for(int i=0; i<2*n; ++i) cin>>a[i]; sort(a,a+2*n,cmp); int ans=0; for(int i=0; i<2*n; ++i){ if(prime[a[i]]) { if(mpp[a[i]]>0){ --mpp[a[i]]; continue; } cout<<a[i]<<" "; ++ans; for(it=mp.begin(); it!=mp.end(); ++it) if(a[i]%(it->first)==0){ ++mpp[a[i]/(it->first)]; break; } } else{ if(mpp[a[i]]==0){ cout<<mp[a[i]]<<" "; ++mpp[mp[a[i]]]; ++ans; } else --mpp[a[i]]; } if(ans==n) break; } return 0; }