Daliy Algorithm (最短路,位运算)-- day 87
Nothing to fear
种一棵树最好的时间是十年前,其次是现在!
那些你早出晚归付出的刻苦努力,你不想训练,当你觉的太累了但还是要咬牙坚持的时候,那就是在追逐梦想,不要在意终点有什么,要享受路途的过程,或许你不能成就梦想,但一定会有更伟大的事情随之而来。 mamba out~
2020.6.5
人一我十,人十我百,追逐青春的梦想,怀着自信的心,永不言弃!
LG-P1461海明码
考点:位运算
补充知识:
获取二进制中 1 的个数__builtin_popcount
如何判断两个数字的汉明距离:
将两个数字进行异或
a ^ b 判断异或后还剩余多少个1汉明距离就是几。
#include <iostream>
#include <cstdio>
#include <string>
#include <set>
#include <algorithm>
using namespace std;
const int N = 105;
int n , b , d;
int a[N];
int getbit(int x)
{
int cnt = 0;
while(x)
{
cnt += x & 1;
x >>= 1;
}
return cnt;
}
int main()
{
cin >> n >> b >> d;
int len = 2;
for(int i = 1;i <= (1 << b) ;i ++)
{
if(len > n)break;
bool flag = 1;
for(int j = 1;j <= len ;j ++)
{
if(__builtin_popcount(a[j] ^ i) < d)
{
flag = 0;break;
}
}
if(flag)a[len++] = i;
}
for(int i = 1;i < len;i ++)
{
cout << a[i] << " ";
if(i % 10 == 0)cout << endl;
}
return 0;
}
LG-P4144 大河的序列
位运算微观结论推理
贪心+位运算
对于任意一个数aa, 我们分析这个数加入序列后会发生的变化
那么对于a的二进制表示从高到低进行讨论
如果是1: 那么 bitand 的值不会变少, 而且如果原来 bitor 的二进制表示在这一位上是0, 那么就会变成1
如果是0: 那么 bitor 的值不会变多, 而且如果原来 bitand 的二进制表示在这一位上是1, 那么就会变成0
综上所述, 我们要取的a应该尽可能在高位上是1, 所以a应该最大
其实就是结论题目
max(a[l,r]) * 2 = max((a[l] & a[l+1] & ... & a[r]) + (a[l] | a[l+1] | ... | a[r]));
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstdlib>
using namespace std;
const int N = 100005;
int n , b , p;
int cal(int a , int b, int p)
{
int ans = 1;
while(b)
{
if(b & 1)ans = (1ll)*ans * a % p;
a = (1ll)*a * a % p;
b >>= 1;
}
return ans;
}
int main()
{
cin >> n >> b >> p;
int x = 0 , ans = 0;
for(int i = 1;i <= n ;i ++)
{
cin >> x;
ans = max(ans , x);
}
cout << cal(ans * 2 + 233 , b , p) % p;
return 0;
}
紧急救援
最短路
Dijkstar + 记录路径 + 记录点权值 + 记录路径条数
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <vector>
#include <queue>
using namespace std;
#define INF 0x3f
const int N = 505;
int n , m , s , d;
int w[N], dis[N], pre[N], weight[N], num[N];
bool vis[N];
int g[N][N];
void Dijkstra(int start)
{
for(int i = 0;i < n ;i ++)dis[i] = 0x3f;
dis[0] = 0;num[start] = 1;w[start] = weight[start];
// 找到一个未被访问过的距离源点最小的点
// 一开始是起始点
for(int i = 1;i <= n - 1;i ++)
{
int minc = INF,u = -1;
for(int j = 0;j < n ;j ++)
{
if(!vis[j] && dis[j] < minc)
{
minc = dis[j];
u = j;
}
}
if(u == -1)break;
vis[u] = 1;
for(int v = 0;v < n ;v ++)
{
if(dis[v] > dis[u] + g[u][v])
{
dis[v] = dis[u] + g[u][v];
num[v] = num[u];
w[v] = w[u] + weight[v];
pre[v] = u;
}
else if(dis[v] == dis[u] + g[u][v])
{
num[v] = num[v] + num[u];
if(w[u] + weight[v] > w[v])
{
w[v] = w[u] + weight[v];
pre[v] = u;
}
}
}
}
}
void printpath(int v)
{
if(v == s)
{
printf("%d", v);
return;
}
printpath(pre[v]);
printf(" %d", v);
}
void input()
{
memset(g , 0x3f , sizeof g);
cin >> n >> m >> s >> d;
for(int i = 0 ;i < n ;i ++)scanf("%d",&weight[i]);
for(int i = 0 ;i < m ;i ++)
{
int a , b ,c;
scanf("%d %d %d",&a ,&b , &c);
g[a][b] = g[b][a] = c;
}
Dijkstra(s);
printf("%d %d\n",num[d] , w[d]);
printpath(d);
}
int main()
{
input();
return 0;
}