uva 269 - Counting Patterns(构造)

题目链接:uva 269
- Counting Patterns

题目大意:给出n和k,要求找出满足的序列,要求为n元组,由-k到k组成,并且和为0。求出所有满足的元组个数,并且对于左移,右移,水平翻转,每个元素取相反数相同的视为一种,用字典序最大的表示,输出按照字典序最小的输出。

解题思路:因为表示的时候按照字典序最大的表示,一开始枚举开头的位置,那么在后面的数的绝对值就不会大于该数。最后判断一下,如果该序列不是最优的表示方法,就不是该情况。

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

using namespace std;
const int maxn = 100005;
const int maxm = 15;

int s[maxn][maxm];
int n, k, key, cnt, a[maxm];

void put (int num[]) {
    printf("(%d", num[0]);
    for (int i = 1; i < n; i++)
        printf(",%d", num[i]);
    printf(")\n");
}

bool cmp (int l[], int r[]) {
    for (int i = 0; i < n; i++)
        if (l[i] != r[i])
            return l[i] > r[i];
    return false;
}

void check () {
    int b[maxm*2];

    for (int i = 0; i < n; i++)
        b[i] = b[i+n] = a[i];
    for (int i = 0; i < n; i++)
        if (b[i] == a[0] && cmp(b+i, a))
            return;

    for (int i = 0; i < 2 * n; i++)
        b[i] = -b[i];
    for (int i = 0; i < n; i++)
        if (b[i] == a[0] && cmp(b+i, a))
            return;

    for (int i = 0; i < n; i++)
        swap(b[i], b[2*n-i-1]);
    for (int i = 0;  i < n; i++)
        if (b[i] == a[0] && cmp(b+i, a))
            return;

    for (int i = 0; i < 2 * n; i++)
        b[i] = -b[i];
    for (int i = 0; i < n; i++)
        if (b[i] == a[0] && cmp(b+i, a))
            return;

    memcpy(s[cnt++], a, sizeof(a));
}

void dfs (int d, int sum) {
    if (d == n) {
        if (sum == 0)
            check();
        return;
    }

    if (abs(sum) > ((n - d) * a[0]))
        return;

    for (a[d] = -key; a[d] < key; a[d]++) {
        if (a[d-1] == key && a[d] > a[1])
            return;
        dfs(d + 1, sum + a[d]);
    }

    if (a[d] == key && a[d-1] <= a[1])
        dfs(d+1, sum+a[d]);
}

int main () {
    int cas = 0;
    while (scanf("%d%d", &n, &k) == 2 && n) {
        cnt = 1;
        for (a[0] = 1; a[0] <= k; a[0]++) {
            key = a[0];
            dfs(1, key);
        }

        if (cas++)
            printf("\n");
        printf("%d\n", cnt);
        for (int i = 0; i < cnt; i++)
            put(s[i]);
    }
    return 0;
}

uva 269 - Counting Patterns(构造)

时间: 2024-08-23 21:30:38

uva 269 - Counting Patterns(构造)的相关文章

UVA - 12075 Counting Triangles

Description Triangles are polygons with three sides and strictly positive area. Lattice triangles are the triangles all whose vertexes have integer coordinates. In this problem you have to find the number of lattice triangles in anMxN grid. For examp

uva 1449 - Dominating Patterns(AC自动机)

题目练级:uva 1449 - Dominating Patterns 题目大意:有一个由小写字母组成的字符串集和一个文本T,要求找出那些字符串在文本中出现的次数最多. 解题思路:将字符串集建立AC自动机,然后传入T进行匹配,对每个匹配上的字符串多应次数加1,最后找出最大值.出现次数与最大值相同的字符串输出.注意字符集中出现相同字符的情况. #include <cstdio> #include <cstring> #include <queue> #include &l

UVA - 10574 Counting Rectangles

Description Problem H Counting Rectangles Input: Standard Input Output:Standard Output Time Limit: 3Seconds   Given n points on the XY plane, count how many regular rectanglesare formed. A rectangle is regular if and only if its sides are all paralle

uva 12075 - Counting Triangles(容斥原理)

题目链接:uva 12075 - Counting Triangles 题目大意:一个n?m的矩阵,求说有选任意三点,可以组成多少个三角形. 解题思路:任意选三点C(3(n+1)?(m+1))但是有些组合是不可行得,即为三点共线,除了水平和竖直上的组合,就是斜线上的了,dp[i][j]即为ij情况下的斜线三点共线. #include <cstdio> #include <cstring> typedef long long ll; const int N = 1005; ll dp

uva 1436 - Counting heaps(计数)

题目链接:uva 1436 - Counting heaps 题目大意:给出一个树的形状,现在为这棵树标号,保证根节点的标号值比子节点的标号值大,问有多少种标号树. 解题思路:和村名排队的思路是一只的uva11174,最后问题只和树德结构有直接关系,f(root)=(s(root)?1)!(s(1)?s(2)???s(n) 但是给定的取模数不是质数,所以不能用逆元做,只能将分子分母分别拆分成质因子,然后对质因子进制约分.因为最后的答案一定是正整数,所以对于每个质因子,分子分解出的因子个数一定大于

UVA 12075 - Counting Triangles(容斥原理计数)

题目链接:12075 - Counting Triangles 题意:求n * m矩形内,最多能组成几个三角形 这题和UVA 1393类似,把总情况扣去三点共线情况,那么问题转化为求三点共线的情况,对于两点,求他们的gcd - 1,得到的就是他们之间有多少个点,那么情况数就可以求了,然后还是利用容斥原理去计数,然后累加出答案 代码: #include <stdio.h> #include <string.h> #include <algorithm> using nam

UVA 1436 - Counting heaps(计数问题)

UVA 1436 - Counting heaps 题目链接 题意:给定一个树的结构,放1-n数字进去,父亲结点值必须小于子节点,问情况有几种. 思路:f[u]表示以u为子树的情况,那么子树情况为f(v1), f(v2), f(v3)... f(vn).去组成子树相当于从中选s(v1), s(v2), s(v3) ... s(vn).根据组合数学,情况为f(v1) f(v2) ... f(vn) (s(u) - 1)! \ (s(v1)! s(v2)! ... * s(vn)!)化简后得到公式:

UVA 11123 - Counting Trapizoid(计数问题+容斥)

UVA 11123 - Counting Trapizoid 题目链接 题意:给定一些点,不重复,求出一共有几个梯形 思路:先把所有两点组成直线求出来,然后排序,斜率相同的C2n个,然后再扣除掉重叠的直线情况和长度相等情况(这样为平行四边形或矩形),由于扣除的时候会重复扣掉重叠和相等,所以在加回来,这是容斥原理. 代码: #include <stdio.h> #include <string.h> #include <math.h> #include <algor

uva 11123 - Counting Trapizoid(容斥+几何)

题目链接:uva 11123 - Counting Trapizoid 题目大意:给定若干个点,问有多少种梯形,不包括矩形,梯形的面积必须为正数.因为是点的集合,所以不会优重复的点. 解题思路:枚举两两点,求出该条直线,包括斜率k,偏移值c,以及长度l.已知梯形的性质,一对对边平行,也就是说一对平行但是不相等的边. 所以将所有线段按照斜率排序,假设对于某一斜率,有m条边,那么这m条边可以组成的含平行对边的四边形有C(2m),要求梯形还要减掉长度相同以及共线的情况,分别对应的是l相同和c相同,但是