HDU 5080 polya定理

来源:互联网 发布:中国农业大学网络管理 编辑:程序博客网 时间:2024/05/29 19:40

分析: 因为坐标只有整数,所以只能是转90度 或者180 或者 不转。

根据polya定理,我们可以求出所有的方案数, 前提是证明出这个玩具是每转90度相同的还是180度还是不转。

如何证明这个玩具转的角度。我用了暴力枚举的方法,因为n<=50,O(n^4)算法足够了,是这样的,枚举任意两个点的中点。

如果这个中点是所有点对的中点,那么这个中点就是旋转点。然后每次逆时针旋转90度,看和原来的边和点是否匹配。

然后根据旋转的角度来计算等价类的个数,具体如何计算等价类,请百度polya定理。参考AC代码:

#include<cstdio>typedef long long LL;const int MOD = 1000000007;struct Point{    double x,y;    Point(double x=0, double y=0){this->x=x;this->y=y;}}p[55],p1[55];bool operator==(const Point &a, const Point &b){    return a.x == b.x && a.y == b.y;}struct Line{    Point a,b;}l[1555],l1[1555];bool operator==(const Line &l1, const Line &l2){    return l1.a == l2.a && l1.b == l2.b || l1.a == l2.b && l1.b == l2.a;}int n, m, c;double x,y;bool find_mid(){    bool flag = false;    for(int i = 1; i <= n; i++){        for(int j = i + 1; j <= n; j++){            x = p[i].x + p[j].x;            y = p[i].y + p[j].y;                flag = true;                for(int k = 1; k <= n; k++){                    Point t(x-p[k].x, y-p[k].y);                    int o;                    for(o = 1; o <= n; o++){                        if(p[o] == t) break;                    }                    if(o > n){flag = false;break;}                }                if(flag) return true;        }    }    return false;}Point rotate(Point a){    return Point(a.y+(-y+x)/2, -a.x+(x+y)/2);}bool rever(Point *pfrom, Line *lfrom, Point *pto, Line *lto){    for(int i = 1; i <= n; i++){        pto[i] = rotate(pfrom[i]);    }    for(int i = 1; i <= m; i++){        lto[i].a = rotate(lfrom[i].a);        lto[i].b = rotate(lfrom[i].b);    }    bool flag = true;    for(int i = 1; i <= n; i++){        int j;        for(j = 1; j <= n; j++){            if(pto[i] == p[j]) break;        }        if(j > n){flag = false; break;}    }    if(flag){        for(int i = 1; i <= m; i++){            int j;            for(j = 1; j <= m; j++){                if(lto[i] == l[j]){                    break;                }            }            if(j > m){flag = false; break;}        }    }    return flag;}int gcd(int a, int b){ return b == 0 ? a : gcd(b, a%b);}LL pow_mod(LL base, int exp){    LL ret = 1;    while(exp){        if(exp&1) ret = ret * base % MOD;        base = base * base % MOD;        exp >>= 1;    }    return ret;}LL rev(int d){    return pow_mod(d, MOD-2);}LL cal(int d){    LL r = (n % d == 0 ? 1 : c);    n /= d;    LL ans = 0;    for(int i = 0; i < d; i++){        ans = (ans + pow_mod(c, n * gcd(i, d))) % MOD;    }    ans = ans * rev(d) % MOD;    return ans * r % MOD;}int main(){   // freopen("1.txt","r",stdin);    int T;scanf("%d", &T);    while(T--){        scanf("%d%d%d", &n, &m, &c);        for(int i = 1; i <= n; i++){            scanf("%lf%lf", &p[i].x, &p[i].y);        }        int a,b;        for(int i = 1; i <= m; i++){            scanf("%d%d", &a, &b);            l[i].a = p[a];            l[i].b = p[b];        }        int d;        if(find_mid()){            if(rever(p,l,p1,l1)){                d = 4;            }else if(rever(p1,l1,p1,l1)){                d = 2;            }else d = 1;        }else d = 1;        printf("%I64d\n", cal(d));    }    return 0;}<strong></strong>


0 0
原创粉丝点击