目录
K-图上计数
思路:观察到可以删除任意边来获得若干连通块,其实就是有n个点,组成两个连通块,求图的代价最大值,与边无关(赛时没看到,在那并查集+dfs。。。),只需要将点平分成两个连通块,求乘积就行。
代码:
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define MOD 10000000007
#define INF 0x3f3f3f3f
const int N=1e5+5;
void solve()
{
int n,m;cin>>n>>m;
for(int i=0;i<m;i++)
{
int u,v;cin>>u>>v;
}
if(n<=1) cout<<0;
else if(n==2) cout<<1;
else if(n%2==1) cout<<(n/2)*(n/2+1);
else if(n%2==0) cout<<(n/2)*(n/2);
}
signed main()
{
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
// int _;cin>>_;while(_--)
solve();
}
F-两难抉择新编
思路:暴力题,用一个数组记录异或和,枚举1~x,对其进行加或乘,取最大值即可。
代码:
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define MOD 10000000007
#define INF 0x3f3f3f3f
const int N=2e5+5;
int a[N];
void solve()
{
int n;cin>>n;int sum=0,ans=0;
for(int i=1;i<=n;i++) cin>>a[i],sum^=a[i];
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n/i;j++)
{
ans=max(ans,sum^a[i]^(a[i]+j));
ans=max(ans,sum^a[i]^(a[i]*j));
}
}
cout<<ans;
}
signed main()
{
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
// int _;cin>>_;while(_--)
solve();
}
G-旅途的终点
思路:注意到会超过long long,所以在找到答案后直接返回,采用优先队列,当优先队列中的元素个数大于k时,考虑使用生命力来畅游所需生命力少的国家,所需大的国家使用神力抵消,直到所需生命力大于等于总生命力时则无法继续畅游。复杂度:O(nlogn)。
代码:
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define MOD 10000000007
#define INF 0x3f3f3f3f
const int N=2e5+5;
int a[N];
void solve()
{
int n,m,k;cin>>n>>m>>k;int sum=0;
for(int i=1;i<=n;i++) cin>>a[i];
priority_queue <int,vector<int>,greater<int> >q;//将所需生命力从小到大排,优先抵扣小的
for(int i=1;i<=n;i++)
{
q.push(a[i]);//入队
if(q.size()>k)//当神力无法全部畅游考虑使用生命力抵扣
{
sum+=q.top();//用生命力畅游当前所需最小的国家
q.pop();
}
if(sum>=m)//生命力不够直接输出答案
{
cout<<i-1<<endl;return;
}
}
cout<<n<<endl;
}
signed main()
{
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
// int _;cin>>_;while(_--)
solve();
}
D-小蓝的二进制询问
思路:从低位到高位观察,第一位隔两次出现一次1,第二位隔四次出现一次1,第三位隔八次出现一次1........直接计算即可,注意处理余数,求1~r与1~l-1的个数,相减即可。
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define mod 998244353
#define INF 0x3f3f3f3f
const int N=1e5+5;
int f(int x)
{
int res=0,a=2;
x++;//包含x
while(a/2<=x)
{
res+=(x/a)*(a/2);res%=mod;//计算第a/2位的个数
res+=max(0,(x%a-(a/2)));res%=mod;//计算余数
}
}
void solve()
{
int l,r;cin>>l>>r;
cout<<f(r)-f(l-1)<<endl;
}
signed main()
{
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
int _;cin>>_;while(_--)
solve();
}
B-爱探险的朵拉
思路:最多可以探险的关卡数就是各个关卡所组成的最大环或者最长链的大小,官方题解是拓扑排序,并更新环的点的数量。应该是数据弱了,dfs直接搜也能过。
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
#define MOD 10000000007
#define INF 0x3f3f3f3f
const int N=1e5+5;
int a[N],b[N],ma=0;
void dfs(int fi,int x,int l)
{
ma=max(ma,l);
if(b[x]!=fi)
{
b[x]=fi;//更新每个关卡的前置关卡,判断是否成环
dfs(fi,a[x],l+1);
}
}
void solve()
{
int n;cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];
for(int i=1;i<=n;i++)
{
if(!b[i]) dfs(i,i,0);
}
cout<<ma;
}
signed main()
{
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
// int _;cin>>_;while(_--)
solve();
}