数论7.13
7.13 数论练习#
P4301 新Nim游戏#
思路:
考虑这是 游戏,想要先手必胜,就要让对方在第一回合无论拿走几堆后剩下的所有堆异或和都不为
考虑线性基,若插进去的 最后为 就说明 不能插
所以搞一下贪心,将所有石子堆 按个数从大到小遍历
能插就插,否则就拿走
简单证一下:如果对于 那么根据 可知拿走 更优
所以让大的先插进去会更优
// Problem: P4301 [CQOI2013] 新Nim游戏
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P4301
// Memory Limit: 125 MB
// Time Limit: 1000 ms
#include<bits/stdc++.h>
using namespace std;
#define int long long
inline int read(){
int x=0,f=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-') f=-1;ch=getchar();}
while(isdigit(ch)){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
return x*f;
}
const int N=105;
int n;
int a[N],p[N];
signed main(){
n=read();
int ans=0;
for(int i=1;i<=n;++i) a[i]=read();
sort(a+1,a+n+1);
for(int i=n;i;--i){
int x=a[i];
for(int j=31;j>=0;--j){
if((1<<j)&x){
if(p[j]) x^=p[j];
else{
p[j]=x;
break;
}
}
}
if(!x) ans+=a[i];
}
cout<<ans;
}
P4151 最大XOR和路径#
思路:
由于是最大异或和,考虑线性基
显然对于 到 的路径上每一个环都可以选择遍历
分两种情况讨论:
- 到 只有一条路径,此时把路径上可遍历的所有的环的异或和扔进线性基,求最大就行
- 到 不止一条路径,此时 和 也在一个环内,这样我们可以随机选一条路径,同时把 所在的也扔进线性基求最大就行
#include<bits/stdc++.h>
using namespace std;
const int N=5e4+5;
#define ll long long
#define int long long
#define pb push_back
inline ll read(){
ll x=0,f=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-') f=-1;ch=getchar();}
while(isdigit(ch)){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
return x*f;
}
struct fake_pair{
ll a,b;
};
int n,m;
bool vis[N];
ll dis[N],p[N];
vector <fake_pair> G[N];
inline void insert(ll x){
for(ll i=63;i>=0;--i)
if(x&(1ll<<i)){
if(!p[i]){
p[i]=x;
return;
}
x^=p[i];
}
}
inline ll query(ll x){
for(ll i=63;i>=0;--i)
if((x^p[i])>x)
x^=p[i];
return x;
}
inline void dfs(ll x,ll sum){
vis[x]=1;
dis[x]=sum;
for(auto y:G[x]){
if(vis[y.a]) insert(sum^y.b^dis[y.a]);
else dfs(y.a,sum^y.b);
}
}
signed main(){
n=read(),m=read();
for(int i=1;i<=m;++i){
ll x=read(),y=read(),z=read();
G[x].pb({y,z});
G[y].pb({x,z});
}
dfs(1,0);
cout<<query(dis[n]);
}
平面最近(远)点对#
我们充分发扬人类智慧,把所有点按 从小到大排序
根据数学直觉,取后 个点可以求得最近距离
#include<bits/stdc++.h>
using namespace std;
const int N=2e5+5;
inline int read(){
int x=0,f=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-') f=-1;ch=getchar();}
while(isdigit(ch)){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
return x*f;
}
int n;
struct pt{
double x,y;
inline bool operator < (const pt A) const {
return x==A.x?y<A.y:x<A.x;
}
}a[N];
inline double dist(pt A,pt B){
return (A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y);
}
signed main(){
n=read();
double mn=1000000000000000000;
for(int i=1;i<=n;++i) scanf("%lf %lf",&a[i].x,&a[i].y);
sort(a+1,a+n+1);
for(int i=1;i<=n;++i){
for(int j=i+1;j<=min(i+20,n);++j)
mn=min(mn,dist(a[i],a[j]));
}
printf("%.4lf",sqrt(mn));
}
上面的方法被卡了
我们充分发扬人类智慧,将 均加上 并按 从小到大排序
根据数学直觉,取后 个点可以求得最近距离
#include<bits/stdc++.h>
using namespace std;
const int N=4e5+5;
#define re register
#define int long long
#define nm 2333
inline int read(){
int x=0,f=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-') f=-1;ch=getchar();}
while(isdigit(ch)){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
return x*f;
}
int n;
struct pt{
int x,y;
inline bool operator < (const pt A) const {
return (x+nm)*(y+nm)>(A.x+nm)*(A.y+nm);
}
}a[N];
inline int dist(pt A,pt B){
return (A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y);
}
signed main(){
n=read();
int mn=1000000000000000;
for(int i=1;i<=n;++i) a[i].x=read(),a[i].y=read();
sort(a+1,a+n+1);
for(re int i=1;i<=n;++i){
for(re int j=i+1;j<=min(i+900,n);++j)
mn=min(mn,dist(a[i],a[j]));
}
printf("%lld",mn);
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 按钮权限的设计及实现