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;
}
posted @ 2020-06-06 10:12  _starsky  阅读(87)  评论(0编辑  收藏  举报