其他分享
首页 > 其他分享> > 高2018级NOIP模拟赛20190813

高2018级NOIP模拟赛20190813

作者:互联网

文章目录


非做顽石不可,哪管他敬仰暗唾。堕尘泥,桃源藏胸,仗剑执花如昨


写在前面

这次考试大意啦>_<,最后一道题错的不应该呀,dp很简单的

T1 异或求值

传送门:mzoj #31

题目

描述
求1到n的异或值,即123…^n

输入
一个数n
输出
一个数,表示所求出的值

样例

输入
3
输出
0

数据范围
50% 1<=n<=10^6
100% 1<=n<=10^18

分析

打表找规律,也可以自己证
O(1)

代码

/*************************
User:Mandy.H.Y
Language:c++
Problem:xor
Algorithm: 
*************************/

#include<bits/stdc++.h>
#define Max(x,y) ((x) > (y) ? (x) : (y))
#define Min(x,y) ((x) < (y) ? (x) : (y))

using namespace std;

typedef long long ll;

ll n;

template<class T>inline void read(T &x){
	x = 0;bool flag = 0;char ch = getchar();
	while(!isdigit(ch)) flag |= ch == '-',ch = getchar();
	while(isdigit(ch)) x = (x << 1) + (x << 3) + (ch ^ 48),ch = getchar();
	if(flag) x = -x;
}

template<class T>void putch(const T x){
	if(x > 9) putch(x / 10);
	putchar(x % 10 | 48);
} 

template<class T>void put(const T x){
	if(x < 0) putchar('-'),putch(-x);
	else putch(x);
}

void file(){
	freopen("xor.in","r",stdin);
	freopen("xor.out","w",stdout);
}

void readdata(){
	read(n);
}

void work(){
	ll res = n % (ll)4;
	switch(res){
		case 0:{put(n);break;}
		case 1:{put(1);break;}
		case 2:{put(n + 1);break;}
		default:{put(0);break;}
	}
}

int main(){
//	file();
	readdata();
	work();
	return 0;
}

T2 染色方案

传送门:luogu3914

题目

描述
有一颗N 个节点的树,节点用1, 2…N 编号。你要给它染色,使得相邻节点的颜色不同。有M 种颜色,用1,2…M 编号。每个节点可以染M 种颜色中的若干种,求不同染色方案的数量除以(10^9 + 7)的余数。

输入(color.in)
第1 行,2 个整数N,M,接下来N 行,第i 行表示节点i 可以染的颜色。第1个整数ki,表示可以染的颜色数量。接下来ki个整数,表示可以染的颜色编号。最后N-1 行,每行2个整数Ai,Bi表示边(Ai,Bi)。

输出(color.out)
一行一个数,即答案

样例
输入
2 2
1 1
2 1 2
1 2
输出
1

数据范围
对于30% 的数据, 1<=N<=10; 1<=M<=4;
对于60% 的数据, 1<=N<=200; 1<=M<=200;
对于100% 的数据,1<=N<=5000; 1<=M<=5000 1<=ki 所有ki的和<=1000000

分析

树形DP,这种方案计数一般和乘法原理与加法原理有点关系诶
从下到上分析;
举个栗子:
在叶节点假如情况是这样的:
在这里插入图片描述
则 父节点的方案数:
颜色1:2 * 4 * 2
颜色2:2 * 3 * 2
颜色3:2 * 3 * 2
颜色4:3 * 3 * 3
颜色5:3 * 3 * 3
颜色6:3 * 4 * 3
类比若到了树上任意一点
在这里插入图片描述
方案数变必须考虑子树的方案数了,但其实也是一样的,即:
颜色 i 的方案数:
儿子 1 不为颜色 i 的方案总数 * 儿子 1 不为颜色 i 的方案总数 * ……

代码

/*************************
User:Mandy.H.Y
Language:c++
Problem:color
Algorithm: 
*************************/

#include<bits/stdc++.h>
#define Max(x,y) ((x) > (y) ? (x) : (y))
#define Min(x,y) ((x) < (y) ? (x) : (y))

using namespace std;

const int maxn = 5005;
const int mod = 1e9 + 7;

typedef long long ll;
int n,m,size,first[maxn];
bool color[maxn][maxn],judge;
int dp[maxn][maxn],cnt[maxn];

struct Edge{
	int v,nt;
}edge[maxn << 1];

template<class T>inline void read(T &x){
	x = 0;bool flag = 0;char ch = getchar();
	while(!isdigit(ch)) flag |= ch == '-',ch = getchar();
	while(isdigit(ch)) x = (x << 1) + (x << 3) + (ch ^ 48),ch = getchar();
	if(flag) x = -x;
}

template<class T>void putch(const T x){
	if(x > 9) putch(x / 10);
	putchar(x % 10 | 48);
} 

template<class T>void put(const T x){
	if(x < 0) putchar('-'),putch(-x);
	else putch(x);
}

void file(){
	freopen("color.in","r",stdin);
	freopen("color.out","w",stdout);
}

void eadd(int u,int v){
	edge[ ++ size].v = v;
	edge[size].nt = first[u];
	first[u] = size;
}

void readdata(){
	read(n);read(m);
	for(int i = 1;i <= n; ++ i){
		read(cnt[i]);
		if(!cnt[i]) judge = 1;
		for(int j = 1;j <= cnt[i]; ++ j) {
			int x;
			read(x);
			color[i][x] = 1;
//			dp[i][x] = 1;
		}
	}
	for(int i = 1;i < n; ++ i){
		int u,v;;
		read(u);read(v);
		eadd(u,v);eadd(v,u);
	}
}

void dfs(int u,int f){
	
	ll res = 0;

		for(int j = first[u];j;j = edge[j].nt){
			int v = edge[j].v;
			if(v == f) continue;
			dfs(v,u);
		}
	
	for(int i = 1;i <= m; ++ i){
		ll sum = 1;
		if(! color[u][i]) continue;
		for(int j = first[u];j;j = edge[j].nt){
			int v = edge[j].v;
			if(v == f) continue;

			if(color[v][i]) sum = sum * ((ll)dp[v][0] - dp[v][i] + mod) % mod;
			else sum = sum * (ll)dp[v][0] % mod;
		}

		dp[u][i] = (int)(sum % mod);
		
		res = (res + sum) % mod;
	}
	
	dp[u][0] = (int)res;
	
}

void work(){
	dfs(1,0);
	put(dp[1][0]);
}

int main(){
//	file();
	readdata();
	if(judge) {
		puts("0");
		return 0;
	}
	work();
	return 0;
}

T3 新三国争霸

题目传送门:codevs1403

题目

描述 Description
PP 特别喜欢玩即时战略类游戏,但他觉得那些游戏都有美中不足的地方。灾害总不降临道路,而只降临城市,而且道路不能被占领,没有保护粮草的真实性。于是他就研发了《新三国争霸》。
在这款游戏中,加入灾害对道路的影响(也就是一旦道路W[i,j]受到了灾害的影响,那么在一定时间内,这条路将不能通过)和道路的占领权(对于一条道路W[i,j],至少需要K[i,j]个士兵才能守住)。
PP可真是高手,不一会,就攻下了N-1座城市,加上原来的就有N座城市了,但他忽略了一点……那就是防守同样重要,不过现在还来的及。因为才打完仗所以很多城市都需要建设,PP估算了一下,大概需要T天。他现在无暇分身进攻了,只好在这T天内好好的搞建设了。所以他要派士兵占领一些道路,以确保任何两个城市之间都有路(不然敌人就要分而攻之了,是很危险的)。士兵可不是白干活的,每个士兵每天都要吃掉V的军粮。因为有灾害,所以方案可能有变化(每改变一次就需要K的军粮,初始方案也需要K的军粮)。
因为游戏是PP编的,所以他知道什么时候有灾害。PP可是一个很节约的人,他希望这T天在道路的防守上花最少的军粮。
输入格式 InputFormat
第一行有5个整数N,M,T,V,K。N表示有城市数,M表示道路数,T表示需要修养的天数,V表示每个士兵每天吃掉的军粮数,K表示修改一次花掉的军粮数。
以下M行,每行3个数A,B,C。表示A与B有一条路(路是双向的)需要C个士兵才能守住。
第M+2行是一个数P,表示有P个灾害。
以下P行,每行4个数,X,Y,T1,T2。表示X到Y的这条路,在T1到T2这几天都会受灾害。
输出格式 OutputFormat
T天在道路的防守上花费最少的军粮。
样例输入 SampleInput
3 3 5 10 30
1 2 1
2 3 2
1 3 4
1
1 3 2 5
样例输出 SampleOutput
180
数据范围和注释 Hint
对于所有数据:N<=300,M<=5000 ,T<=50,P<=8000

分析

最小生成树 + DP;
dp[i]dp[i]dp[i]表示到第iii天总共的最少费用
方程:(ans是第j~i天的共有的最小生成树最低费用)
dp[i]=min(dp[i],dp[j1]+(ij+1)ans+K dp[i] = min(dp[i],dp[j - 1] + (i - j + 1) * ans + K dp[i]=min(dp[i],dp[j−1]+(i−j+1)∗ans+K
有木有很像[ZJOI2006]物流运输?(有诶>_<)
那个专题传送门:综合题 - 图论与动规

代码

/*************************
User:Mandy.H.Y
Language:c++
Problem:three
Algorithm: 
*************************/

#include<bits/stdc++.h>
#define Max(x,y) ((x) > (y) ? (x) : (y))
#define Min(x,y) ((x) < (y) ? (x) : (y))

using namespace std;

const int maxn = 305;
const int maxm = 5005;

int T,N,M,size,V,K,P,now,pre,ans;
int father[maxn]; 
int dp[55];
bool vis[maxn][maxn];
//因为是按边禁,就标记边而不是点 qwq 

struct Val{
	int u,v,w;
}val[maxm];

struct Dis{
	int x,y,l,r;
}dis[8005];

template<class T>inline void read(T &x){
	x = 0;bool flag = 0;char ch = getchar();
	while(!isdigit(ch)) flag |= ch == '-',ch = getchar();
	while(isdigit(ch)) x = (x << 1) + (x << 3) + (ch ^ 48),ch = getchar();
	if(flag) x = -x;
}

template<class T>void putch(const T x){
	if(x > 9) putch(x / 10);
	putchar(x % 10 | 48);
} 

template<class T>void put(const T x){
	if(x < 0) putchar('-'),putch(-x);
	else putch(x);
}

void file(){
	freopen("three.in","r",stdin);
//	freopen("three.out","w",stdout);
}

void add(int u,int v,int w){
	val[++size].v = v;
	val[size].u = u;
	val[size].w = w;
}

bool cmp(const Val &a,const Val &b){
	return a.w < b.w;
}

bool cmp1(const Dis &a,const Dis &b){
	if(a.l != b.l) return a.l < b.l;
	else return a.r < b.r;
}

void readdata(){
	read(N);read(M);read(T);read(V);read(K);
	for(int i = 1;i <= M; ++ i){
		int u,v,w;
		read(u);read(v);read(w);
		add(u,v,w);
	}
	
	sort(val + 1,val + 1 + M,cmp);
	
	read(P);
	
	for(int i = 1;i <= P; ++ i){
		read(dis[i].x);	read(dis[i].y);	read(dis[i].l);	read(dis[i].r);
	}

	sort(dis + 1,dis + 1 + P,cmp1);
}

int find(int x){
	return father[x] == x ? x : father[x] = find(father[x]);
}

void merge(int x,int y){
	father[find(x)] = find(y);
}

int kruskal(int x,int y){
	for(int i = 1;i <= N; ++ i) father[i] = i;
	memset(vis,0,sizeof(vis));

	for(int i = 1;i <= P; ++ i){
		if(dis[i].l > y) break;
		if(dis[i].l <= y && x <= dis[i].r){
			vis[dis[i].x][dis[i].y] = 1;
			vis[dis[i].y][dis[i].x] = 1;
		}
	}
	
	int cnt = 0,cost = 0;
	
	for(int i = 1;i <= M; ++ i){
		int v = val[i].v;
		int u = val[i].u;
		int w = val[i].w;
		
		if(vis[u][v]) continue;
		if(find(u) != find(v)){
			merge(u,v);
			cost += w * V;
			++cnt;
		}
		if(cnt == N - 1) return cost;
	}
	return -1;
}

void work(){
	memset(dp,0x3f3f3f3f,sizeof(dp));
	dp[0] = 0;
	for(int i = 1;i <= T; ++ i){
		
		for(int j = i;j >= 1; -- j){
			int ans = kruskal(j,i);
			if(ans == -1) continue;
			dp[i] = min(dp[i],dp[j - 1] + (i - j + 1) * ans + K);
		}
		
	}
	put(dp[T]);
}

int main(){
//	file();
	readdata();
	work();
	return 0;
}

标签:ch,const,NOIP,int,void,20190813,2018,putch,dp
来源: https://blog.csdn.net/weixin_44584560/article/details/99477611