POLYA合集

hdu 4633 Who's Aunt Zhang

polya计数,费马小定理

分为以下几种循环节:

初始态;对面旋转;对点旋转;对棱旋转

幸好题目规模不大,肉眼完全可以数出来

#include<cstdio>
#include<algorithm>
#include<vector>
#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std;
const int mod = 10007;
int k;
int mpower(int b, int a)
{
	int res = 1, p = b;
	while (a)
	{
		if (a & 1) res = res*p%mod;
		p = p*p%mod;
		a >>= 1;
	}
	return res;
}
int cal()
{
	int res = 0;
	res += mpower(k, 54+8+12);
	res += mpower(k, 3+3+9+3+2)*3;
	res += mpower(k, 5+5+18+6+4)*3;
	res += mpower(k, 3+3+9+3+2)*3;
	res += mpower(k, 27+7+4)*6;
	res += mpower(k, 18+4+4)*4;
	res += mpower(k, 18+4+4)*4;
	res %= mod;
	return res*mpower(24, mod-2)%mod;
}
int main()
{
#ifndef ONLINE_JUDGE
	freopen("in.txt", "r", stdin);
#endif
	int t, cs = 1;
	scanf("%d", &t);
	while (t--)
	{
		printf("Case %d: ", cs++);
		scanf("%d", &k);
		printf("%d\n", cal());
	}
	return 0;
}

hdu 3441 Rotation

即便是借鉴了别人的思路,还是费了不少力气。
新学到了利用欧拉函数优化环形polya计数的方法
若数据庞大,分解质因子后搜索可大幅提升效率
#include<cstdio>
#include<algorithm>
#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std;
typedef __int64 ll;
const ll mod = 1000000007;
const int MAXN = 32000;
bool isPrime[MAXN] = {false};
ll prime[MAXN], res, color, all, ssm;
int np = 0;
void init()
{
    for (int i = 2; i< MAXN; ++i)
    {
        if (!isPrime[i]) 
            prime[np++] = i;
        for (int j = 0; j<np && prime[j]*i< MAXN; ++j)
        {
            isPrime[prime[j]*i] = true;
            if (i % prime[j] == 0) break;
        }
    }
}

ll mpower(ll b, ll a)
{
    ll res = 1, p = b%mod;    // 失误点:b可能大于mod 
    while (a)
    {
        if (a & 1) res = res*p%mod;
        p = p*p%mod;
        a >>= 1;
    }
    return res;
}
ll getTran(ll a, ll c)
{
    const ll ny = mpower(4, mod-2);
    if (a & 1)
    {
        return (mpower(c, a*a) + mpower(c, (a*a+3)>>2)*2%mod
            + mpower(c, (a*a+1)>>1))*ny%mod;
    }
    else
    {
        return (mpower(c, a*a) + mpower(c, (a*a)>>2)*2%mod + mpower(c, (a*a)>>1))*ny%mod;
    }
}
ll fact[100], fenjie[100][2];
int nfac, nfen;
void addFac(ll aa)    // 失误点:本例中素数未全部列出 
{
    for (int i = 0; i< np && prime[i]*prime[i] <= aa; ++i)
    {
        while ( aa % prime[i] == 0) aa /= prime[i], fact[nfac++] = prime[i];
    }
    if (aa != 1) fact[nfac++] = aa;
}
void dfs2(int idx, ll x, ll sa, ll sb, ll a, ll c)
{
    if (idx == nfen)
    {
        ll k = a / x; 
        ssm = (ssm + mpower(c, k)*(x/sa*sb%mod)%mod)%mod;
    }
    else
    {
        ll cn = 0, p = fenjie[idx][1], q = fenjie[idx][0];
        for ( ; cn <= p; ++cn)
        {
            if (cn == 0) dfs2(idx+1, x, sa, sb, a, c);
            else dfs2(idx+1, x, sa*q, sb*(q-1), a, c);
            x *= q;
        }
    }
}
void dfs(int idx, ll b)
{
    if (idx == nfen)
    {
        ll ncol = getTran(b, color);
        ll k = (all*all-1)/b/b;
        ssm = 0;
        dfs2(0, 1, 1, 1, k, ncol);
        ssm = ssm*mpower(k, mod-2)%mod;
        res = (res + ssm)%mod;
    }
    else
    {
        ll cn = 0, s = fenjie[idx][1];
        for ( ; cn <= s; )
        {
            fenjie[idx][1] -= cn;            
            dfs(idx+1, b);
            fenjie[idx][1] += cn;
            cn += 2;
            b *= fenjie[idx][0];
        }
    }
}
ll solve()
{
    res = 0;
    nfac = 0;
    nfen = 0;
    addFac(all-1); addFac(all+1);
    sort(fact, fact + nfac);
    fenjie[0][0] = fact[0]; fenjie[0][1] = 1;
    for (int i = 1; i< nfac; ++i)
    {
        if (fact[i] == fact[i-1])
        {
            fenjie[nfen][1]++;
        }
        else
        {
            nfen++;
            fenjie[nfen][0] = fact[i];
            fenjie[nfen][1] = 1;
        }
    }
    nfen++;
    dfs(0, 1);
    return res*color%mod;
}
int main()
{
#ifndef ONLINE_JUDGE
    freopen("in.txt", "r", stdin);
#endif
    int t, cs = 0;
    init();
    scanf("%d", &t);
    while (t--)
    {
        printf("Case %d: ", ++cs);
        scanf("%I64d%I64d", &all, &color);
        if (all == 1) printf("%I64d\n", color);
        else
            printf("%I64d\n", solve());
    }
    return 0;
}

hdu 3547 DIY Cube

Java的大数用着就是爽
import java.math.BigInteger;
import java.util.Scanner;

public class Main
{
	static Scanner cin = new Scanner(System.in);
	public static void main(String[] args)
	{
		final BigInteger mod = BigInteger.valueOf(10).pow(15);
		int t = 0, cs = 1;
		t = cin.nextInt();
		while ((t--) != 0)
		{
			System.out.print("Case "+(cs++)+": ");
			BigInteger c = cin.nextBigInteger(), p;
			BigInteger sum = BigInteger.valueOf(0), cnt = BigInteger.valueOf(24);
			p = c.pow(8);
			sum = sum.add(p);
			p = c.pow(2).multiply(BigInteger.valueOf(6));
			sum = sum.add(p);
			p = c.pow(4).multiply(BigInteger.valueOf(17));
			sum = sum.add(p);
			sum = sum.divide(cnt);
			
			if (sum.compareTo(mod) > 0)
			{
				sum = sum.mod(mod);
				String msString = sum.toString();
				for (int i = msString.length(); i < 15; ++i)
					System.out.print(0);
			}		
			System.out.println(sum);			
		}
	}
}


hdu 2865 Birthday Toy

polya及其优化,组合数学
对于每种置换,不变的着色方案数的计算 可转化为 环着色,根据题意
为n个节点的环着m种颜色且相邻节点颜色不同的方案数为:(m-1)^a + (-1)^n * ((m-1)^3 - m*(m-1)*(m-2))
需要注意的是若n == 1,则方案数为0(题目的特殊性质决定)
#include<cstdio>
#include<algorithm>
#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std;
typedef __int64 ll;
const ll mod = 1000000007;
const int MAXN = 32000;
bool isPrime[MAXN] = {false};
ll prime[MAXN], np = 0;
ll nn, mm;
void initPrime()
{
	for (int i = 2; i< MAXN; ++i)
	{
		if(!isPrime[i]) prime[np++] = i;
		for (int j = 0; j<np && i*prime[j]<MAXN; ++j)
		{
			isPrime[i*prime[j]] = true;
			if (i % prime[j] == 0) break;
		}
	}
}
ll npow(ll a, ll b)
{
	ll res = 1, p = a%mod;
	while (b)
	{
		if (b & 1) res = res*p%mod;
		p = p*p % mod;
		b >>= 1;
	}
	return res;
}
ll fenzi[100][2];
int nfen;
void divide(ll a)
{
	for (int i = 0; i< np && prime[i]*prime[i] <= a; ++i)
	{
		if (a % prime[i] == 0)
		{
			fenzi[nfen][0] = prime[i]; fenzi[nfen][1] = 0;
			while (a % prime[i] == 0)
			{
				a /= prime[i];
				fenzi[nfen][1]++;
			}
			nfen++;
		}
	}
	if (a != 1)
	{
		fenzi[nfen][0] = a; fenzi[nfen++][1] = 1;
	}
}
ll resAll;
ll getCircle(ll m, ll n)
{
	ll res;
	if (n == 1) return 0;
	if (n == 2) return m*(m-1)%mod;
	res = (npow(m-1, 3) - m*(m-1)%mod*(m-2)%mod)%mod;
	res = n&1?-res:res;
	res = (res + mod)%mod;
	res = (res + npow(m-1, n)) % mod;
	return res;
}
void dfs(int i, ll p1, ll p2, ll x)
{
	if (i == nfen)
	{
		ll t = nn/x;
		resAll = (resAll + getCircle(mm-1, t)*(x/p1*p2%mod)%mod)%mod;		
	}else
	{
		int cnt = 0, p = fenzi[i][1], q = fenzi[i][0];
		for ( ;cnt <= p; ++cnt)
		{
			if (!cnt) dfs(i+1, p1, p2, x);
			else dfs(i+1, p1*q, p2*(q-1), x);
			x *= q;
		}
	}
}
ll solve()
{
	nfen = 0;
	resAll = 0;
	divide(nn);
	dfs(0, 1, 1, 1);
	return resAll*npow(nn, mod-2)%mod*mm%mod;
}
int main()
{
#ifndef ONLINE_JUDGE
	freopen("in.txt", "r", stdin);
#endif
    initPrime();
    while (scanf("%I64d%I64d", &nn, &mm) != EOF)
    {
		printf("%I64d\n", solve());
    }
    return 0;
}


hdu 5080 Colorful Toy

核心是找出置换群,所以先找中心,再根据置换的步数暴力搜索
#include <stdio.h>
#include <vector>
#include <string>
#include <algorithm>
#include <queue>
#include <cstring>
#include <map>
#include <set>
#include <iostream>
#include <cmath>
using namespace std;
typedef long long LL;
const int MAXN = 55;
const LL MOD = 1e9+7;
const double eps = 1e-8, PI = acos(-1.0);
inline int zero(double a)
{
    return (a>eps) - (a<-eps);
}
struct _Point
{
    double x, y;
    double angle, dis;
    _Point (double x=0.0, double y=0.0) {this->x=x; this->y=y;}
    bool operator == (const _Point & a) const
    {
        return !zero(x-a.x) && !zero(y-a.y);
    }
    void getDis()
    {
        dis = sqrt(x*x + y*y);
    }
    _Point rota(double ag)
    {
        return _Point(dis*cos(angle+ag), dis*sin(angle+ag));
    }
} pt[MAXN], center;
bool mmp[MAXN][MAXN];
int n, m, c;
int P[MAXN], cnt, Permt[MAXN], np;
bool cmp(const int a, const int b)
{
    if (zero(pt[a].angle - pt[b].angle) != 0) return pt[a].angle < pt[b].angle;
    return (pt[a].dis) < (pt[b].dis);
}
int check_pt()
{
    double rs = pt[Permt[P[0]]].angle - pt[P[0]].angle;
    for (int i = 0; i< cnt; ++i)
    {
        if (!(pt[Permt[P[i]]] == pt[P[i]].rota(rs)))
            return 0;
    }
    return 1;
}
int check_link()
{
    for (int i = 0; i< n; ++i)
    {
        for (int j = 0; j< n; ++j)
            if (mmp[i][j] != mmp[Permt[i]][Permt[j]]) return 0;
    }
    return 1;
}
bool vis[MAXN];
LL mpow(LL a, LL b)
{
    LL res = 1, p = a;
    while (b)
    {
        if (b & 1) res = res*p%MOD;
        p = p*p%MOD;
        b >>= 1;
    }
    return res;
}
LL solve()
{
    int ans = 0;
    memset(vis, 0, sizeof vis);
    for (int i = 0; i<n; ++i)
    {
        if (!vis[i])
        {
            ++ans;
            for (int tp=i; !vis[tp]; tp = Permt[tp])
                vis[tp] = 1;
        }
    }
    return mpow(c, ans);
}
int main()
{
#ifndef ONLINE_JUDGE
    freopen("in.txt", "r", stdin);
    //freopen("out.txt", "w", stdout);
#endif // ONLINE_JUDGE
    int t, u, v;
    scanf("%d", &t);
    while (t--)
    {
        scanf("%d%d%d", &n, &m, &c);
        center.x = center.y = 0.0;
        for (int i = 0; i< n; ++i)
            scanf("%lf%lf", &pt[i].x, &pt[i].y), center.x += pt[i].x, center.y += pt[i].y;
        center.x /= n;
        center.y /= n;
        cnt = 0;
        for (int i = 0; i< n; ++i)
        {
            pt[i].x -= center.x;
            pt[i].y -= center.y;
            pt[i].getDis();
            if (pt[i] == center)
            {
                Permt[i] = i;
                continue;
            }
            pt[i].angle = atan2(pt[i].y, pt[i].x);
            P[cnt++] = i;
        }
        sort(P, P+cnt, cmp);
        memset(mmp, 0, sizeof mmp);
        for (int i = 0; i< m; ++i)
        {
            scanf("%d%d", &u, &v);
            --u; --v;
            mmp[u][v] = mmp[v][u] = 1;
        }
        LL res = 0LL;
        np = 0;
        for (int i = 0; i< cnt; ++i)  // 转过i个单位
        {
            for (int j = 0; j< cnt; ++j)
                Permt[P[j]] = P[(i+j)%cnt];
            if (check_pt() && check_link())
            {
                ++np;
                res = res + solve();
            }
        }
        cout<<res*mpow(np,MOD-2)%MOD <<endl;
    }
    return 0;
}





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值