love 疑惑
思路:前缀和异或
前缀和预处理后
判断 i 前面的区间的异或和 和 i 后面区间的异或和异或是否为i,若为i则输出i。
注意边界问题
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=1e5+10;
int a[N],s[N];
//s[r]^s[l-1]
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
int n;
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>a[i];
s[i]=s[i-1]^a[i];
}
if(a[1]==s[n]^s[1])
{
cout<<a[1]<<endl;
return 0;
}
if(a[n]==s[n-1]^s[0])
{
cout<<a[n]<<endl;
return 0;
}
for(int i=2;i<=n;i++)
{
if(((s[i-1]^s[0])^(s[n]^s[i]))==a[i])
{
cout<<a[i]<<endl;
break;
}
}
return 0;
}
排列
栈不栈
思路:我是直接模拟的,数据比较水直接过了
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=200010;
int q[N];
int tt;
int gcd(int a,int b)
{
return b?gcd(b,a%b):a;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
int q1;
cin>>q1;
while(q1--)
{
int op;
cin>>op;
if(op==1)
{
int x;
cin>>x;
q[++tt]=x;
}
if(op==2)
{
tt--;
}
if(op==3)
{
cout<<q[tt]<<endl;
}
if(op==4)
{
int k;
cin>>k;
int cnt=tt;
int x=gcd(q[tt],q[tt-1]);
for(int i=cnt-2;i>cnt-k;i--)
{
int x=gcd(x,q[i]);
}
for(int i=cnt;i>cnt-k;i--)
{
q[i]=x;
}
}
}
return 0;
}
01010101001010
思路:数据范围比较小,我直接暴力判断所有情况,取最小值
1若a数组==b数组,则直接返回0
2不相等的话,若a[i]!=b[i],res1++
3先排列,若a[i]!=b[i],res2++
取min(res1,res2)
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=1e5+10;
int a[N],b[N];
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
int n;
cin>>n;
for(int i=0;i<n;i++)
{
cin>>a[i];
}
for(int i=0;i<n;i++)
{
cin>>b[i];
}
int res1=0;
int res2=0;
int flag=0;
for(int i=0;i<n;i++)
{
if(a[i]!=b[i])
{
flag=1;
break;
}
}
if(flag==0)
{
cout<<0<<endl;
return 0;
}
else
{
for(int i=0;i<n;i++)
{
if(a[i]!=b[i])
res1++;
}
res2++;
sort(a,a+n);
sort(b,b+n);
for(int i=0;i<n;i++)
{
if(a[i]!=b[i])
res2++;
}
cout<<min(res1,res2)<<endl;
}
return 0;
}
回家
思路:无向图,而且边权为正,所有我们可以用dijkstra模板
#include<iostream>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
typedef pair<int,int> PII;
const int N=1e3+10,M=1e4+10;
int h[N],e[M],ne[M],w[M],idx;
int v[N];
int dist[N];
bool st[N];
int n,m;
int dijkstra()
{
memset(dist,0x3f,sizeof dist);
dist[1]=0;
priority_queue<PII,vector<PII>,greater<PII>> heap;
heap.push({0,1});
while(heap.size())
{
auto t=heap.top();
heap.pop();
int ver=t.second,distance=t.first;
if(st[ver]) continue;
st[ver]=true;
for(int i=h[ver];i!=-1;i=ne[i])
{
int j=e[i];
if(j!=n)
{
if(dist[j]>distance+w[i]+v[j])
{
dist[j]=distance+w[i]+v[j];
heap.push({dist[j],j});
}
}
if(j==n)
{
if(dist[j]>distance+w[i])
{
dist[j]=distance+w[i];
heap.push({dist[j],j});
}
}
}
}
if(dist[n]==0x3f3f3f3f) return -1;
return dist[n];
}
void add(int a,int b,int c)
{
e[idx]=b;
w[idx]=c;
ne[idx]=h[a];
h[a]=idx++;
}
int main()
{
cin>>n>>m;
memset(h,-1,sizeof h);
for(int i=1;i<=n;i++)
{
cin>>v[i];
}
for(int i=0;i<m;i++)
{
int a,b,c;
cin>>a>>b>>c;
add(a,b,c);
add(b,a,c);
}
int t=dijkstra();
cout<<t<<endl;
}
投票
思路:
若n或者m为1,则一定不可以
若m>=n 则此时一定可以
因为我们可以让n个题目每次都获得一票
若n>m
我们判断是否存在n的约数(不为1)小于等于 m
若存在则我们一定可以
举个例子:n=25 , m=7
n的因子5 < m
我们可以选5个题目,每个题目都是5票
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
ll gcd(ll a,ll b)
{
return b?gcd(b,a%b):a;
}
bool check(ll n,ll m)
{
for(int i=1;i<=n/i;i++)
{
if(n%i==0)
{
if(i<=m&&i!=1)
return true;
if(n/i!=i)
{
if(n/i<=m&&i!=1)
{
return true;
}
}
}
}
return false;
}
int main()
{
int T;
cin>>T;
while(T--)
{
ll n,m;
cin>>n>>m;
if(m==1||n==1)
{
puts("NO");
}
else if(m>=n)
{
puts("YES");
}
else
{
if(check(n,m)) puts("YES");
else puts("NO");
}
}
return 0;
}
选数
思路:
我们可以把题目抽象成从s个数里选,其价值就是a[i]的约数之和(不包括其本身),其体积就是a[i]
满足体积不超过s的情况下,让价值最大,且每个数只能选一次,标准的01背包问题
#include<iostream>
#include<algorithm>
#include<vector>
#include<cstring>
using namespace std;
const int N=1e4+10;
int s[N];
int f[N];
int find(int x)
{
int sum=0;
for(int i=1;i<=x/i;i++)
{
if(x%i==0)
{
sum+=i;
if(x/i!=i) sum+=(x/i);
}
}
return sum-x;
}
int main()
{
int n;
cin>>n;
for(int i=1;i<=n;i++)
{
s[i]=find(i);
}
for(int i=1;i<=n;i++)
{
for(int j=n;j>=i;j--)
{
if(j>=i)
{
f[j]=max(f[j],f[j-i]+s[i]);
}
}
}
cout<<f[n]<<endl;
return 0;
}
计数
讲究效率
思路:贪心
1.将每个区间按右端点从小到大排序
2.从前往后以此枚举每一个区间
如果当前区间中已经包含点,则直接pass
否则,选择当前区间右端点
按照这个方式选择的端点数量就是我们最大的不相交的区间的数量
证明我们的方案是对的:
我们方案选择的区间数量是cnt
最优解是ans
证明
1.ans>=cnt
按照这种方案选出来的区间相互之间是没有交集的
通过这种方式选出来的区间一定是我们可行的方案
我们答案是所有可行方案的最大值
因此ans>=cnt
2.ans<=cnt
按照这种方式会选出cnt个点,每个区间至少包含一个我们选择的点
假设ans>cnt
就意味着我们可以选出来比cnt更多个没有交集的空间
但由于我们cnt个点,已经把所有区间的覆盖掉,即每个区间都至少包含一个点
如果有>cnt个不相交的区间,那么我们至少要选择ans个点才能把所有区间覆盖掉,与实际情况不符
因为我们实际只用选择cnt个点就能覆盖所有区间
因此ans<=cnt
//做法与上道题一样,重要的是如何证明你的方案可以找出最优解
//1.将每个区间按右端点从小到大排序
//2.从前往后以此枚举每一个区间
//如果当前区间中已经包含点,则直接pass
//否则,选择当前区间右端点
#include<iostream>
#include<algorithm>
#include<vector>
#include<cstring>
using namespace std;
const int N=2e5+10;
int n;
struct Range
{
int l,r;
bool operator<(const Range &W)const
{
return r<W.r;
}
}range[N];
int main()
{
scanf("%d",&n);
for(int i=0;i<n;i++)
{
int l,r;
scanf("%d%d",&l,&r);
range[i]={l,r};
}
sort(range,range+n);
int res=0,ed=-2e9;
for(int i=0;i<n;i++)
{
if(range[i].l>=ed)
{
res++;
ed=range[i].r;
}
}
printf("%d\n",res);
return 0;
}