第四届湘潭邀请赛解题报告

   本场比赛由我、白翔、木连组成的iBeyond完成。

   很水的一个比赛,没有特别难的算法,也没有特别难的题,做了8题,1题线段树、1题线段树优化DP、1题博弈、1题m叉哈夫曼树,其他4题都是模拟题。


A题 Anti-Goldbach's Conjecture 题目要求求2个函数,一个g(x)、一个sg(x)(x都为奇数),g(x)表示1<= i < x中,i为合数且它和另一个合数相加得x。只要算出x-2(因为x-2加上2为x不合法)之前奇数个数减去素数个数(2要特判),再累加起来算sg(x)。


C题 Collatz Conjecture 模拟题,题目要求的过程,一个数一个数的算经过的次数和经过的最大值,次数累加,最大值中取最大者输出即可。


D题 Data Encoding  m叉哈夫曼树,求用m个字符表示长度为n的字符串的最小长度,题目看不太懂,到现在还没看懂,但看了样例以后发现是哈夫曼树,并且不是二叉的,那就是m叉的。求解时利用一个优先队列即可。但这题要特判,判断叶节点num % (n - 1) 是否等于 1 % (n - 1),如果不足,就用0补上知道满足为止,为什么这样呢?因为节点不足不处理的话,大的数却是在后面处理,这样最后算出来的长度最大。而那个等式,大家画一画m叉哈夫曼树就懂了。


E题 Echo 模拟题,第一行全部输出,第二行不熟第一个单词,第三行不熟第二个单词,以此类推。


F题 Flip the Bits  博弈题,给定一个超大的数,把它化成二进制数,可以把某个为1的i位翻为0,直到某个人没得翻的时候他就输了,但有一个前提,i翻的话每个它的因子都可以翻,正是这个规定让这题变得简单。先判断每一位单独翻的时候要走几步,可以用一个bool数组,true表示N点,false表示P点。最后输入n的时候,把2...n之间的N点上的值抑或起来,最后如果为true则为N点,false为P点。


G题 Girls and Boys 模拟题,刚看题目觉得是稳定婚姻匹配,然后各种YY,套用一个模版交上去华丽丽地Wa了,觉得男追女不妥,改成nv追男,但是天理不容,也Wa了。在Wa了几次之后仔细看了遍题目,发现在一起了后不能分手,这是多么悲剧啊,人的一生只有一个女朋友或男朋友,出题者的思想....其实思想和稳定婚姻匹配差不多,但这题要逆向而行,先匹配最不喜欢的人,有喜欢的再更新,这样就可以不分离了。


I题 Interview Arrangement  线段树优化DP。一开始觉得是贪心,如果每场考试价值一样的话就肯定是贪心,尽量多选择。但现实是残酷的,将每场时间按结束时间排序,并把每个时间离散化(因为n只有10万,那不一样的时间最多20万个,用map进行映射即可)。排完序之后明显就没有后效性了,最后的那场考试肯定是从他的开始时间之前的最大价值转移而来,而这之前的那个最大值又可以从开始之前的最大值转移而来。状态转移方程:dp[arr[i].end] = max(dp[i]) + arr[i].val;(i为大于arr[i].begin的时间,离散化之后范围为20万).如果这样暴力的花复杂度是O(n^2),拒绝暴力,求最大值,可以用线段树保存,每次更新的话单点更新,查询的花查询1--arr[i].begin内的最大值。总复杂度O(nlogn);


J题 Josephus Problem 线段树,约瑟夫环变形。说了这么多题,不多说了,贴个代码。

//C++
#include<iostream>
#include<stdio.h>
using namespace std;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1


int ans[100001];
int xw[100001];
const int maxn=200000;
int w,sum[maxn<<2];


void build(int l,int r,int rt){///建立线段树

    sum[rt] = r - l + 1;
    if(l == r) return ;
    int m = (l+r) >> 1;
    build(lson);
    build(rson);
}
int update(int p,int l,int r,int rt){///更新单个节点
	
	sum[rt]--;
	if(l == r) return l ;
	int m = (l + r) >> 1;
	if(p <= sum[rt<<1])
        return    update(p,lson);
	else
        return   update(p-sum[rt<<1],rson);
	
}


int main()
{
	int n,m,i;
	int x,A,B,M;


    while(scanf("%d%d%d%d%d%d",&n,&m,&x,&A,&B,&M)!=EOF)
    {
        build(1,n,1);
        int z = 1;
        for(i = 1; i <= n; i++)
        {
            z = ((int)x+z)%sum[1];
            if(z == 0) z = sum[1];
            int s = update(z,1,n,1);
            ans[i] = s;
            x = (int)(((__int64)x * A + B) % M);
        }
        for(i = 0; i < m; i++)
            scanf("%d",&xw[i]);
		
		
        for(i=0;i<m-1;i++)
			printf("%d ",ans[xw[i]]);
        if(m!=0) printf("%d",ans[xw[m-1]]);
        printf("\n");
    }
    return 0;
}

本文ZeroClock原创,但可以转载,因为我们是兄弟。 

你可能感兴趣的:(c,优化,算法,Build,encoding)