• 月考简要题解


    模拟赛简要题解

    一下题目均可在loj上找到

    10178. 「一本通 5.5 例 4」旅行问题

    简单题,将n扩大到2 * n,单调队列即可,注意正反向.

    #include<iostream>  
    #include<cstring>  
    #include<cmath>  
    #include<cstdio>  
    #include<algorithm>  
    using namespace std;  
    typedef long long ll;  
    const int N=2000005;
    ll sum[N];
    int p[N],d[N],que[N],ok[N];
    int n;
    
    inline int read() {
    	int x = 0,f = 1;char c = getchar();
    	while(c < '0' || c > '9') {if(c == '-')f = -1;c = getchar();}
    	while(c >= '0' && c <= '9') {x = x * 10 + c - '0';c = getchar();}
    	return x * f;
    }
    void DP1()
    {
    	int q1 = 1,q2 = 0;
    	for (int i = 1; i <= n; ++ i){
    		while (q1 <= q2 && sum[que[q2]] >= sum[i]) -- q2;
    		que[++ q2]=i;
    	}
    	for (int i = n + 1; i <= n * 2; ++ i){
    		while (q1 <= q2 && sum[que[q2]] >= sum[i]) -- q2;
    		que[++ q2] = i;
    		while (q1 <= q2 && que[q1] <= i - n) ++ q1;
    		if (sum[que[q1]] >= sum[i - n]) ok[i-n] = 1;	
    	}
    }
    void DP2()
    {
    	int q1 = 1,q2 = 0;
    	for (int i = n * 2; i > n; -- i){
    		while (q1 <= q2 && sum[que[q2]] >= sum[i]) -- q2;
    		que[++ q2] = i;
    	}
    	for (int i = n; i; -- i){
    		while (q1 <= q2 && sum[que[q2]] >= sum[i]) -- q2;
    		que[++ q2] = i;
    		while (q1 <= q2 && que[q1] >= i + n) ++ q1;
    		if (sum[que[q1]] >= sum[i + n]) ok[i] = 1;		
    	}
    }
    int main()  
    {  
     	n = read();
     	for(int i = 1;i <= n;++ i) {
     		p[i + n] = p[i] = read(),d[i + n] = d[i] = read();
    		 sum[i] = sum[i - 1] + p[i - 1] - d[i - 1];	
     	}
     	for(int i = n + 1;i <= 2 * n;++ i) 
     		sum[i] = sum[i - 1] + p[i - 1] - d[i - 1];
     	DP1();
     	for(int i = n * 2 ;i; -- i) 
    		sum[i] = sum[i + 1] + p[i + 1] - d[i];
     	DP2();
     	for(int i = 1;i <= n;++ i) 
     		ok[i] ? puts("TAK") : puts("NIE");
     	return 0;
    }  
    

    10078. 「一本通 3.2 练习 4」新年好

    简单题,spfa跑六边最短路,全排列枚举即可.

    #include <iostream>
    #include <cstring>
    #include <queue>
    #include <cstdio>
    const int maxN = 5e4 + 7;
    const int maxM = 1e5 + 7;
    using namespace std;
    
    int ke_dis[maxN][7];
    queue <int>q;
    bool vis[maxN];
    int dis[maxN];
    
    int Q[7],n,m; 
    
    struct Node {
    	int v,nex,w;
    }Map[maxM << 1];
    int head[maxN],num;
    
    void add_Node(int u,int v,int w) {
    	Map[++ num] = (Node) {v,head[u],w};
    	head[u] = num;
    	return ;
    }
    
    inline int read() {
    	int x = 0,f = 1;char c = getchar();
    	while(c < '0' || c > '9') {if(c == '-')f = -1;c = getchar();}
    	while(c >= '0' && c <= '9') {x = x * 10 + c - '0';c = getchar();}
    	return x * f;
    }
    
    void spfa(int beg,int bh) {
    	memset(dis,0x3f,sizeof(dis));
    	dis[beg] = 0;
    	q.push(beg);
    	vis[beg] = true;
    	while(!q.empty()) {
    		int p = q.front();q.pop();vis[p] = false;
    		for(int i = head[p];i;i = Map[i].nex) {
    			int v = Map[i].v;
    			if(dis[v] > dis[p] + Map[i].w) {
    				dis[v] = dis[p] + Map[i].w ;
    				if(!vis[v]) {
    					q.push(v);
    					vis[v] = true;
    				}
    			}
    		}
    	}
    	for(int i = 1;i <= n;++ i) 
    		ke_dis[i][bh] = dis[i];
    	return;
    }
    
    long long ans;
    bool is_ch[7];
    int ch[7];//五个亲戚走的顺序 , 只是编号 Q[编号] 是车站的编号 
    //特殊的Q[0] = 1 亲戚应该为1  
    
    void work() {
    	long long sum = 0;
    	for(int i = 1;i <= 5;++ i) {
    		sum += (long long) ke_dis[Q[ch[i - 1]]][ch[i]];
    	}
    	ans = min(ans,sum); 
    } 
    
    void dfs(int tot) {
    	if(tot == 6) work();
    	for(int i = 1;i <= 5;++ i) {
    		if(!is_ch[i]) {
    			ch[tot] = i;is_ch[i] = true;
    			dfs(tot + 1);
    			is_ch[i] = false;
    		}
    	}
    }
    
    int main() {
    	n = read();m = read();
    	Q[0] = 1;
    	for(int i = 1;i <= 5;++ i)
    		Q[i] = read();
    	for(int i = 1,u,v,w;i <= m;++ i) {
    		u = read();v = read();w = read();
    		add_Node(u,v,w);	
    		add_Node(v,u,w);
    	}
    	for(int i = 0;i <= 5;++ i) 
    		spfa(Q[i],i);
    	ans = 1e12;
    	dfs(1);
    	printf("%lld", ans);
    	return 0;
    }
    

    #10220. 「一本通 6.5 例 2」Fibonacci 第 n 项

    最简单的题目.
    套一个矩阵乘法即可.

    #include <iostream>
    #include <cstring>
    #include <cstdio>
    #define ll long long
    using namespace std;
    
    struct Node {
    	ll w[4][4];
    	Node() {
    		memset(w,0,sizeof(w));
    	}
    };
    ll n,m;
    
    Node mul(Node a,Node b) {
    	Node c;
    	for(ll i = 1;i <= 2;++ i) {
    		for(ll j = 1;j <= 2;++ j) {
    			for(ll k = 1;k <= 2;++ k) {
    				c.w[i][j] = ( c.w[i][j] + a.w[i][k] * b.w[k][j] ) % m;
    			}
    		}
    	}
    	return c;
    }
    
    void fast_pow(ll b) {
    	Node a,ans;
    	a.w[1][1] = a.w[1][2] = a.w[2][1] = 1;
    	ans.w[1][1] = ans.w[2][2] = 1;
    	for(;b;b >>= 1,a = mul(a,a) ) {
    		if(b & 1) ans = mul(ans,a);
    	}
    	Node tmp;
    	tmp.w[1][1] = tmp.w[1][2] = 1;
    	ans = mul(tmp,ans);
    	printf("%lld", ans.w[1][1]);
    	return ;
    }
    
    int main() {
    	scanf("%lld%lld",&n,&m);
    	if(n == 1) {puts("1");return 0;}
    	if(n == 2) {puts("1");return 0;}
    	fast_pow(n - 2);
    	return 0;
    }
    

    考试收获

    题目一定要读好,读准.
    不然像这次, (300 -> 220)
    暴力一定要打.
    不然(250)分的暴力.
    提高自己的码力和代码查错水平
    现在,Gzy我现在要开始认真了呢.

  • 相关阅读:
    秦腾与教学评估【前缀和+二分】
    c++中成员函数声明时const得作用
    分形【递归】
    飞行兄弟【二进制枚举+异或】
    爬取4k图片网图片
    爬虫爬取博客园文章的文字【练手】
    【YBTOJ】求 f 函数
    【YBTOJ】划分数列
    【学习笔记】高斯消元法
    【Luogu P4588】 [TJOI2018]数学计算
  • 原文地址:https://www.cnblogs.com/tpgzy/p/9768574.html
Copyright © 2020-2023  润新知