UESTC 2014 Summer Training #16 Div.2

  虽然被刷了还是要继续战斗下去嗯...就是基础不好,难度相对较大

A.SPOJ AMR10A

  点是顺时针给出的,可以在图上画画(脑补也行),连线x-a,x-b(x为选定的一个点,比如第一个点),就把所求面积分成了四部分,a-b左边部分是较容易求出来的,

三角形面积是直接可求,另外两个多边形面积是可以预处理出来的(多个三角形面积和)

  反正我是沒想出來...看題解也理解半天,多邊形面積转化为三角形面积和 嗯嗯

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>

using namespace std;

const int maxn = 50000+50;

struct Point{
    long long x, y;

    Point() {}

    Point(long long x, long long y) {
        this->x = x;    this->y = y;
    }

}a[maxn];

int N, Q;
long long sum[maxn];

long long getArea(Point a, Point b, Point c)
{
    return abs( (c.y-a.y)*(b.x-a.x)-(b.y-a.y)*(c.x-a.x) );
}

int main()
{
#ifdef LOCAL
    freopen("A.in", "r", stdin);
#endif
    scanf("%d%d", &N, &Q);
    for(int i = 1; i <= N; i++) {
        long long x, y;
        scanf("%lld%lld", &x, &y);
        a[i] = Point(x, y);
    }
    for(int i = 3; i <= N; i++)
        sum[i] = sum[i-1] + getArea(a[1], a[i-1], a[i]);
    while(Q--) {
        int u, v;
        scanf("%d%d", &u, &v);
        u++;    v++;
        if(v < u)    swap(u, v);
        long long ans = sum[N] - sum[v] + getArea(a[1], a[u], a[v]) + sum[u];
        ans = min(ans, sum[N]-ans);
        if(ans%2 != 0)    printf("%lld.5\n", ans/2);
        else    printf("%lld.0\n", ans/2);
    }
    return 0;
}

C.SPOJ AMR11C

  可以转化为二分图的最大带权匹配问题,连边+KM

  连边朴素的dfs是会挂掉的,2^25,这里介绍一个方法解决这类求子集和的问题,meet-in-the-middle algorithm

  http://www-ti.informatik.uni-tuebingen.de/~reinhard/krypto/English/4.5.1.e.html

  大致意思是先预处理出前一半元素能组合出的数,2^13个,并且排序,然后枚举后一半能组合出的数s2,二分查找sum-s2是否存在,时间复杂度是可以接受的,具体看以上链接

  不过KM算法我不会呢...先扔这里吧

F.SPOJ AMR10F

  水题

#include <iostream>
#include <cstdio>
#include <cstdlib>

using namespace std;

int T, N, A, D;

int main()
{
    cin >> T;
    while(T--) {
        cin >> N >> A >> D;
        cout << (2*A+(N-1)*D)*N/2 << endl;
    }
    return 0;
}

G.SPOJ AMR10G

  队友搞出来的...我没怎么思考,就是排序后,检查每一个区间的极差,算有点贪心,每次选取连续的k个

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>

using namespace std;

const int maxn = 20000+50;
const int inf = ~0u >> 1;

int T, k, n;
int h[maxn];

int main()
{
#ifdef LOCAL
    freopen("G.in", "r", stdin);
#endif
    scanf("%d", &T);
    while(T--) {
        scanf("%d%d", &n, &k);
        for(int i = 0; i < n; i++)
            scanf("%d", h+i);
        sort(h, h+n);
        int ans = inf;
        for(int i = 0; i+k <= n; i++)
            ans = min(h[i+k-1]-h[i], ans);
        printf("%d\n", ans);
    }
    return 0;
}

H.SPOJ AMR10H

  贪心的做法,考虑最小的两个概率一定要放在最两边(选择最两边时,耗时最大)...不要问我为什么= =

  最后算下gcd除去就可以了  ps:  gcd(a,0) = a

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>

using namespace std;

const int maxn = 40;

int T, n, a, b, c;
int p[maxn], arranged[maxn];

int gcd(int a, int b)
{
    return b == 0 ? a: gcd(b, a%b);
}

int main()
{
#ifdef LOCAL
    freopen("H.in", "r", stdin);
#endif
    scanf("%d", &T);
    while(T--) {
        scanf("%d%d%d%d", &n, &a, &b, &c);
        for(int i = 0; i < n; i++)
            scanf("%d", p+i);
        sort(p, p+n);
        int front = 0, rear = n-1;
        for(int i = 0; i < n; i++)
            arranged[i%2?rear--:front++] = p[i];
        int ans = 0;
        for(int i = 0; i < n; i++)
            for(int j = 0; j < n; j++)
                ans += arranged[i]*arranged[j]*((i-j)*(i-j)*a+b*abs(i-j)+c);
        printf("%d/%d\n", ans/gcd(ans, 10000), 10000/gcd(10000, ans));
    }
    return 0;
}

I.SPOJ AMR10I

  这道题我是无论如何也想不到这样优化的...

  N=a1+a2+...+an,  P=a1a2...an

  a1...an都能唯一分解为素数相乘,因此P一定是2~N的素数乘积,似乎通过一个素数表来dfs

  现在要考虑另一点(很多blog没有指出) 最原始的办法是dfs 1~N 现在我们dfs这个素数表,是否覆盖了所有的情况呢?

  事实上2,3的组合就能覆盖2~N的所有数,即使用素数替换之前dfs的数

  例如10 = 6+4  原始的做法会去 dfs 4 6  而现在dfs  2 2 2 3 素数的组合

  想了半天其实自己也不是很理解...

  PS:第一次使用set 资料给出基本操作都是O(logn)!!

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <set>

using namespace std;

const int prime[] = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71};  

int T, N, P;
set<long long> cnt;

void dfs(int x, int r, long long p)
{
    if(x >= 20)    return;
    cnt.insert(p);
//    cout << "insert " << p <<endl;
    if(r < prime[x])    return;
    dfs(x, r-prime[x], p*prime[x]%P);
    //if(r < prime[x+1])    return;
    dfs(x+1, r, p);
}

int main()
{
#ifdef LOCAL
    freopen("I.in", "r", stdin);
#endif
    scanf("%d", &T);
    while(T--) {
        scanf("%d%d", &N, &P);
        cnt.clear();
        dfs(0, N, 1ll);
        printf("%d\n", cnt.size());
    }
    return 0;
}

UESTC 2014 Summer Training #16 Div.2

时间: 2024-12-24 18:49:37

UESTC 2014 Summer Training #16 Div.2的相关文章

UESTC 2014 Summer Training #3 Div.2

(更新中) A:ZOJ 3611 BFS+状态压缩 [题意]:给定一张n*m的图,图上每个点有如下情况:L,R,D,U:代表在该点上只能往它已经给定的方向前进.#,W:不能走到该点.$:走到该点,可以花两分钟得到一分值,然后可以从该点向任意方向走.0:走到该点后可以向任意方向走.然后给你起点和终点坐标,问是否能从起点走到终点,如果能,求出可获得的最大分值以及与之对应达到该最大分值所需的的最小时间花 费.(其中起点和终点坐标可以相同)[知识点]:BFS+状态压缩[题解]:我觉得超级棒的题!真心感觉

UESTC 2014 Summer Training #5 Div.2

持续更新中 B:URAL 1874 三分搜索 [题意]: 给出两条边a,b以及一个墙角,求由这两条边和墙角所构成的四边形的最大面积.[知识点]: 三分搜索[题解]: 将四边形分为两个三角形,其中一个由a,b,以及第三条同时作为墙角斜边的边c,另一个三角形即为墙角与边c构成 则墙角所在的三角形的最大面积为c*c/4,abc变所在的三角形的面积可用海伦公式求出,然后主要是用三分来求这个c,得到c后就可以得到最佳答案了. 还有一种现成的结论...[代码1]: 1 #include <map> 2 #

UESTC 2014 Summer Training #18 Div.2

A.UVALive 6661 题意从1~N中选k个数,和为s的方案数 第一眼搜索,估计错状态量,又去yydp...浪费大量时间 数据很小的,状态数都不会超过2^N...直接dfs就过了 //state二进制表示选取的数 #include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> using namespace std; const int maxn = 200; in

UESTC 2014 Summer Training #7 Div.2

DAY7一开始状态还行,最高纪录rank7,然后没力气了,一直跌到rank24,问题还是很多呐.昨天总结的问题依然很大. Problem A UVA 12377 就一开始还是慌了,没审清楚题意就去WA了一发. 大意是给你一个数字表示的字符串,最高20位,第一表示有N个质数,后面是其幂的非降序排列,所求能表示的数个数. 简单的排列组合题,不过需要处理出2~END的不同划分,并且满足非降序,用dfs处理即可. 具体就是dfs过程中记录下每一个数字出现的次数,因为相同的次数是不计顺序的,需要在统计时除

UESTC 2014 Summer Training #6 Div.2

又是只过两水题,不过状态有些回升,也是差点一血. Problem A SPOJ AMR11A 显然的dp?就一抖就想到尝试从(R,C)推到(1,1),正着推的话,只能检查某一种解可不可行(就有人想出了二分+DP的神奇方法..刚卡过..不过上界是把所有龙加起来..不闲麻烦的话..可以按照贪心的方法先跑一个上界,就每一步选当前最优) 倒着推,龙的话,就加上,药水的话,减去?不够,和1取最大值:某一个点的f[i][j]就是两种策略取最小值: f[i][j] = min{ max(1, f[i+1][j

UESTC 2014 Summer Training #10 Div.2

B.Race to 1 UVA 11762 第一次接触概率dp,完全没想到是dp...没想到能递推出来0 0 首先需要知道 总的期望=每件事的期望×每件事发生的概率 然后可以根据这个来写递推公式,也是dp? 假设不小于x的质数有m个,x的质因子有n个(种 更确切),那么在求X的期望时,可以考虑由他能转移过去的状态转移,X,X/pi p是x的质因子 所以不难得出E(x) = 1+(m-n)/mE(X)+1/msigmaE(X/pi) 注意会加1,因为X转移到后面的情况,就多了一步 //Update

UESTC 2014 Summer Training #11 Div.2

E - Prototype ZOJ 3235 把(d2,0)代入第二个方程可以得到一个方程:经过(d2,0)的抛物线的起点的方程 再把它和第一个方程联立,就能解出两条抛物线的交点,再验算:是否在0~d2范围内,是否在x=d1时会撞到building2 注意可能不需要滑行就能到达(d2,0),先特殊处理这种情况 一开始傻逼理解错题意,后来一直修改又去考虑了不会出现的情况,例如A=0,delta<0,最后才发现了我忘记打sqrt了!!! 这场比赛题略难...就不会做 当时还是比较慌,很怕过不了题,加

UESTC 2014 Summer Training #19

A.UVALive 6161 去迟了,队友已经开始写了,应该是个水题,贴个队友代码 #include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<cmath> #include<map> #include<set> #include<vector> #include<algorithm> #inclu

UESTC 2016 Summer Training #1 Div.2

最近意志力好飘摇..不知道坚不坚持得下去.. 这么弱还瞎纠结...可以滚了.. 水题都不会做.. LCS (A) 水 LCS (B) 没有看题 Gym 100989C 水 1D Cafeteria (B) 不会捉 Gym 100989E 水 Gym 100989F 水 Mission in Amman (B) 没看题 Queue (A) 感觉题意理解得有问题啊 1 #include <iostream> 2 #include <cstdio> 3 #include <cstr