题目意思就是 给n个星球的能量ai
第一个能量是飞船的初始能量,飞船要从i星球到j星球,必须满足a[i]>a[j],并且飞船能量会变成 现在飞船能量 异或 a[j]。
飞船要到第n个星球,求飞船的最大能量。
一开始接触这题,小白赛嘛
打完后有人在群里说线性基线性基
当时晓得个锤子
现在来试试
#include<bits/stdc++.h>
#define ll long long
using namespace std;
int a[3500],p[100],b[3005];
void get(int x){
for(int i=62;i>=0;i--){
if(!(x>>i)){
continue;
}
if(!p[i]){
p[i]=x;
break;
}
x^=p[i];
}
}
int main(){
int n,cnt=0;
int ans=0;
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d",&b[i]);
}
int first=b[1];
if(b[1]<=b[n]){
printf("-1");
return 0;
}
for(int i=2;i<=n-1;i++){
if(b[i]>first){
a[cnt++]=b[i];
}
}
for(int i=0;i<cnt;i++){
get(a[i]);
}
ans=b[1]^b[n];
for(int i=62;i>=0;i--){
if((ans^p[i])>ans){
ans^=p[i];
}
}
if(ans==0){
printf("-1");
}else
printf("%d",ans);
return 0;
}
硬套模板过不了
可能是ans原本就要是0
还是不太理解线性基
就说说正解
首先进行排序
如果第一个星球值小于等于最后一个,直接输出
然后从大到小排序完去从id为1的开始处理到id为n的,因为异或满足结合律
即a ^ (b ^c)=(a ^ b) ^ c
所以我们可以枚举答案,从1<<12-1开始,(为啥是212-1呢?因为4096是大于3000的第一个2的x次方数,所以答案最大只有可能是4095)
然后就是dp了,dp记录的其实用bool就好 ,意义是dp[i]代表飞船的能量能否到达i
#include<bits/stdc++.h>
using namespace std;
const int N=3e3+100;
const int M=1<<12;
int n,ans,tot,dp[M],p[N],a[N];
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d",&p[i]);
}
for(int i=2;i<=n-1;i++){
if(p[1]>p[i]&&p[i]>p[n])
a[tot++]=p[i];
}
dp[p[1]^p[n]]=1;
for(int i=0;i<tot;i++){
for(int j=M-1;j>=0;j--){
dp[j]|=dp[j^a[i]];
}
}
for(int i=M-1;i>=0;i--){
if(dp[i]) {ans=i;break;}
}
ans=p[1]<=p[n]?-1:ans;
return printf("%d\n",ans)*0;
}
代码出自https://blog.csdn.net/Z_sea/article/details/86600771
这个return 赞一个,很秀
为啥是dp[j]|=dp[j^a[i]]呢?因为j ^ a[i]=x的话 那么 x ^ a[i] =j
就是说我们穷举j就是穷举可能的答案,
就是如果飞船能到j,那么必定存在x使得x ^ a[i] =j,所以dp[x]和dp[j]是相同的。
用这种方法就可以了
我们再来看一道题
前置知识:欧拉函数
φ函数的值 通式:φ(x)=x(1-1/p1)(1-1/p2)(1-1/p3)(1-1/p4)……(1-1/pn),其中p1, p2……pn为x的所有质因数,x是不为0的整数。φ(1)=1(唯一和1互质的数(小于等于1)就是1本身)。 (注意:每种质因数只一个。比如12=223那么φ(12)=12*(1-1/2)*(1-1/3)=4)
----摘自百度
另外一篇博客
接下来怎么求欧拉函数呢
LL mul(LL x, LL y,LL p) {
LL ans=0;
while(y){
if(y&1)ans+=x%p;
y>>=1;
x+=x%p;
}
return ans ;
}
LL Phi(LL N) {
LL ans = 1;
for(LL i = 2; i * i <= N; i++) {
if(!(N % i)) {
ans = mul(ans, i - 1); N /= i;
while(!(N % i)) ans *= i, N /= i;
}
}
if(N ^ 1) ans *= N - 1;//n是否为1
return ans;
}
O(根号n)的复杂度,加上位运算
是我见过挺好的模板
小a与黄金街道
反正意思就不说了
挺巧妙的
1-n的所有gcd(n,x)==1的所有x数的和为n*φ(n)/2
牛客上的题解有说怎么来的
所以呢
这题套公式就好了
#include<bits/stdc++.h>
#define LL long long
#define int long long
using namespace std;
const LL mod = 1e9 + 6, mod2 = mod + 1;
LL N, K, A, B;
LL add(LL x, LL y) {
if(x + y < 0) return x + y + mod;
return x + y >= mod ? x + y - mod : x + y;
}
LL mul(LL x, LL y) {
return 1ll * x * y % mod;
}
LL fp(LL a, LL p, LL mod) {
p %= mod;
LL base = 1;
while(p) {
if(p & 1) base = base * a % mod;
a = a * a % mod; p >>= 1;
}
return base;
}
LL Phi(LL N) {
LL ans = 1;
for(LL i = 2; i * i <= N; i++) {
if(!(N % i)) {
ans = mul(ans, i - 1); N /= i;
while(!(N % i)) ans *= i, N /= i;
}
}
if(N ^ 1) ans *= N - 1;
return ans;
}
signed main() {
cin >> N >> K >> A >> B;
LL Lim = 1e13;
assert(A >= 1 && A <= Lim && B >= 1 && B <= Lim);
LL tmp = ((N % mod) * ((Phi(N) / 2) % mod) % mod) ;
LL ans = (A + B) % mod2 * fp(K % mod2, tmp, mod2) % mod2;
cout << ans;
return 0;
}
这个signed main也很秀
long long 不能作为主函数类型,而防止int溢出,很秀的操作
assert终止函数
这是个拓展欧拉定理,吉比特杯学到的
因为Phi(1e9+7)=1e9+6
所以那个指数模的就是1e9+6
原来如此
今儿就到这