• UVA 10294 Arif in Dhaka


    https://vjudge.net/problem/UVA-10294

    题目

    某人看到商店里面有项链和手镯,是由一圈珠子构成的。有k种颜色的珠子,每种珠子随便用,问n个珠子能制作成多少种不同的项链和手镯。

    项链或手镯可以旋转,如果旋转后能够重合的两个项链或者手镯看作一种项链或手镯。

    手镯除了可以旋转以外还可以翻转。如果翻转后能够重合的两个手镯看作一种手镯。

    输入n,k,0<n<51,0<t<11

    输出项链和手镯的种数,保证答案不超过11位数。

    题解

    用Burnside引理 https://oi-wiki.org/math/permutation-group/

    $leftlvert X/G ight vert = frac{1}{leftlvert G ight vert} sum_{gin G} leftlvert X^g ight vert$

    $ X^g={x|xin X,g(x)=x} $

    那么对于项链,有旋转0次、旋转1次、旋转2次……旋转n-1次,如果要求旋转后不变(整个项链看成一个元素,旋转看成置换),那么旋转i次就要求第0,i,2i,3i……个珠子颜色相同,可以得到有$lcm(n,i)/i=n/gcd(n,i)$个珠子颜色相同,这就把项链分成了$gcd(n,i)$份,每一份有t种涂色方式,因此得到项链种数为

    [frac{1}{n}sum_{i=0}^{n-1} {t^{gcd(n,i)}}]

    剩下的还是直接套公式就可以了……

    #include<cstdio>
    using namespace std;
    typedef long long ll;
    int gcd(int a, int b) {
    	return b==0? a:gcd(b,a%b);
    }
    ll qpow(unsigned long long a, int b) {
    	ll ans=1;
    	for(;b;b>>=1) {
    		if(b&1) ans*=a;
    		a*=a;
    	}
    	return ans;
    }
    int main() {
    	int n,t;
    	while(~scanf("%d%d", &n, &t)) {
    		ll ans=0;
    		for(int i=0; i<n; i++) {
    			ans += qpow(t, gcd(n,i));
    		}
    		printf("%lld ", ans/n);
    		if(n&1) {
    			ans+=n*qpow(t,(n+1)/2);
    			printf("%lld
    ", ans/2/n);
    		} else {
    			ans+=n/2*(qpow(t,(n+2)/2)+qpow(t,n/2));
    			printf("%lld
    ", ans/2/n);
    		}
    	}
    }
    
  • 相关阅读:
    Android开发与Sequoyah的安装问题
    Discuz 数据库各表的作用
    jQuery-File-Upload $(...).fileupload is not a function $.widget is not a function
    phpstorm xdebug 无法断点调试问题
    Android Service 启动流程
    Discuz! 全局变量说明
    Discuz! X3 数据表、数据字段说明
    Spring Boot 搭建
    Android组件化开发(注意事项)
    NestedScrollView嵌套RecycleView发生的小问题
  • 原文地址:https://www.cnblogs.com/sahdsg/p/12830979.html
Copyright © 2020-2023  润新知