总结
T1
场上很快就想出来,并且把它做掉了。没有问题。
T2
场上推了一会儿式子,发觉按照长度分类会更简单,于是就很快的把它且掉了,没有问题。
T3
场上想到了一个非常暴力的做法,但是要求最大团,现学了一个贪心的做法。结果最后发现人不需要用最大团。(悲)
题解
T1
不难发觉,如果说我要让每一个字段都拥有当前这个数的话,那么任意两个数之间的间隔不能超过 \(m-1\)。枚举每个数,然后再看它中间是否隔了超过 \(m-1\),如果是输出这个数即可。
代码
#include<bits/stdc++.h>
#define inf 0x3f3f3f3f3f3f3f3f
#define int long long
#define endl '\n'
using namespace std;
const long long maxn=2e5+5;
int a[maxn];
vector<int> v[maxn];
signed main()
{freopen("mex.in","r",stdin);freopen("mex.out","w",stdout);ios::sync_with_stdio(0);cin.tie(0); cout.tie(0);int n,m;cin>>n>>m;for(int i=0;i<maxn;i++) v[i].push_back(0);for(int i=1;i<=n;i++) cin>>a[i],v[a[i]].push_back(i);for(int i=0;i<maxn;i++) v[i].push_back(n+1);int f=-1;for(int i=0;i<maxn;i++){for(int j=1;j<v[i].size();j++){if(v[i][j]-v[i][j-1]>m){f=i;break;}}if(f!=-1){cout<<f;return 0;}}return 0;
}
T2
我们会发现,如果说。长度大于等于三,那么我们如果去枚举,会发现它的枚举的量非常小。于是我们长度大于等于三的我们就去枚举。而小于三的情况只有一个二和一的情况,这个是很好做的。
我们可以解二次函数取二分。如果说\(mid\times (mid+1)\)恰好等于 \(n\) 的话。就有姐,如果无解输出两个 \(n\)。
代码
#include<bits/stdc++.h>
#define inf 0x3f3f3f3f3f3f3f3f
#define int long long
#define endl '\n'
using namespace std;
const long long maxn=2e5+5;
map<int,pair<int,int> > ans;
void init()
{for(int l=1;l<=15000000;l++){int sum=l*(l+1);for(int r=l+2;;r++){sum/=__gcd(sum,r);if(sum>1e18/r) break;sum*=r;if(ans.find(sum)==ans.end()) ans[sum]={l,r};}}
}
signed main()
{freopen("operation.in","r",stdin);freopen("operation.out","w",stdout);ios::sync_with_stdio(0);cin.tie(0); cout.tie(0);init();int t;cin>>t;while(t--){int n;cin>>n;if(ans.find(n)!=ans.end()){cout<<ans[n].first<<' '<<ans[n].second<<endl;continue;}int l=1,r=n,ans=-1;while(l<=r){int mid=(l+r)>>1;int x=n%mid,y=n/mid;if(y==mid+1&&!x){ans=mid;break;}else if(y>=mid+1) l=mid+1;else r=mid-1;}if(ans!=-1) cout<<ans<<' '<<ans+1<<endl;else cout<<n<<' '<<n<<endl;}return 0;
}
T3
我们一开始会去想最的团。但是我们只能用贪心去求,不难发现贪心求最大团不一定能求得出来。
不难发现,题目里面最大团一定很小。因为题目里面写了:边数一定小于K。
于是我们就有了一个比较暴力的做法。
我们去枚举每一个点。每个点和它相邻的点,我们去考虑二进制枚举。如果当前枚举的情况符合条件,那么加入答案中就可以了。
优化比较简单,弄一个标记数组就可以了。这样子可以保证每一个点都只来一次。
时间复杂度 \(O(nk2^k)\)
代码
#include<bits/stdc++.h>
#define inf 0x3f3f3f3f3f3f3f3f
#define int long long
#define endl '\n'
using namespace std;
const int maxn=1e6+5;
set<int> g[maxn];
int in[maxn],vis[maxn],ans,f[maxn];
void solve(vector<int> v)
{int n=v.size();for(int i=0;i<n;i++){f[i]=0;for(int j=0;j<n;j++) if(i==j||g[v[i]].find(v[j])!=g[v[i]].end()) f[i]|=(1<<j);}for(int i=1;i<(1<<n);i++){int flag=1;for(int j=0;j<n;j++)if(((i>>j)&1)==1&&(f[j]&i)!=i){flag=0;break;}if(flag) ans=max(ans,(int)__builtin_popcount(i));}
}
signed main()
{freopen("world.in","r",stdin);freopen("world.out","w",stdout);ios::sync_with_stdio(0);cin.tie(0); cout.tie(0);int n,k;cin>>n>>k;set<pair<int,int> > s;for(int i=0;i<n;i++){int x;cin>>x;in[i]=x;for(int j=0;j<x;j++){int tmp;cin>>tmp;g[i].insert(tmp);}s.insert({in[i],i});}while(!s.empty()){int now=s.begin()->second;s.erase(s.begin());vis[now]=1;vector<int> v;v.push_back(now);for(auto to:g[now]) if(!vis[to]) v.push_back(to);solve(v);for(auto to:g[now]) if(!vis[to]) s.erase({in[to],to}),s.insert({--in[to],to});}cout<<ans;return 0;
}