HDU-5868 Different Circle Permutation

Problem Description
You may not know this but it‘s a fact that Xinghai Square is Asia‘s largest city square. It is located in Dalian and, of course, a landmark of the city. It‘s an ideal place for outing any time of the year. And now:

There are N children from a nearby primary school flying kites with a teacher. When they have a rest at noon, part of them (maybe none) sit around the circle flower beds. The angle between any two of them relative to the center of the circle is always a multiple of 2πN but always not 2πN.

Now, the teacher raises a question: How many different ways there are to arrange students sitting around the flower beds according to the rule stated above. To simplify the problem, every student is seen as the same. And to make the answer looks not so great, the teacher adds another specification: two ways are considered the same if they coincide after rotating.

Input
There are T tests (T≤50). Each test contains one integer N. 1≤N≤1000000000 (109). Process till the end of input.

Output
For each test, output the answer mod 1000000007 (109+7) in one line.

Sample Input
4
7
10

Sample Output
3
5
15

题意为一群孩子按圈排座位。可以看成是给一个项链染色,有两种颜色0和1,同时相邻处不能都染1,若两种染色方案旋转后相同则视为同一种方案。
从题意可以明显的看出,这是一道考察Burnside引理的数论题。
首先,变换方式只有旋转,可以得出,答案应为\( \frac{1}{n}\sum_{i=1}^{n}f(gcd(i,n)) \)。其中f(x)为表示长度为x的一个循环节的染色方案数。

在本题中,考虑最后一个涂1时,则f(x)=f(x-2),最后一个涂0时,则f(x)=f(x-1)。所以f(x)=f(x-1)+f(x+2)。换言之,斐波那契数列。但是同时必须注意的一点是,f(1)=1。因为在循环节长度为1时,若涂1则项链每个环都是1,不符合题意。所以f(1)=1,f(2)=3,f(3)=4,f(4)=7…本人的做法是将f(0)设为2。同时需要注意的一点是,当n=1是,需要特判。对于斐波那契数列,理所当然的想到要使用矩阵快速幂。

同时,考虑到n的数值非常大,直接使用\( \frac{1}{n}\sum_{i=1}^{n}f(gcd(i,n)) \)计算是不可能的。所以对此式进一步简化为\(\sum _{d \mid n} f(gcd(d,n)) * \phi(n/d)\),其中\( \phi() \)函数,即欧拉函数直接计算即可。

而对于\( \frac{1}{n} \),因为10^9+7是质数,直接计算逆元即可。

下面是AC的代码:

  1 #include"cstdio"
  2 #include"cstring"
  3 #include"string"
  4 #include"cstdlib"
  5 #include"vector"
  6 #include"set"
  7 #include"map"
  8 #include"cmath"
  9 using namespace std;
 10 typedef long long LL;
 11
 12 const LL MOD=1000000007;
 13 LL gcd(LL a, LL b)
 14 {
 15     if(b==0) return a;
 16     return gcd(b,a%b);
 17 }
 18 LL powMod(LL x,LL n,LL mod)
 19 {
 20     LL res=1;
 21     while(n>0)
 22     {
 23         if(n&1) res=res*x % mod;
 24         x=x*x % mod;
 25         n>>=1;
 26     }
 27     return res;
 28 }
 29 const LL MAXR=100;
 30 const LL MAXC=100;
 31 struct Matrix
 32 {
 33     LL m[MAXR][MAXC];
 34     LL r,c;
 35     Matrix()
 36     {
 37         r=0,c=0;
 38         memset(m,0,sizeof(m));
 39     }
 40 };
 41 //若不能相乘,返回空矩阵
 42 Matrix operator * (const Matrix &a,const Matrix &b)
 43 {
 44     Matrix ans;
 45     LL r=a.r,c=b.c,x=0;
 46     if(a.c!=b.r) return Matrix();
 47     x=a.c;
 48     ans.r=a.r;
 49     ans.c=b.c;
 50     for (LL i=1; i<=r; i++)
 51         for (LL j=1; j<=c; j++)
 52         {
 53             ans.m[i][j]=0;
 54             for (LL k=1; k<=x; k++)
 55                 ans.m[i][j]=(ans.m[i][j]+a.m[i][k]*b.m[k][j]) % MOD;
 56         }
 57     return ans;
 58 }
 59 //若不能乘方,返回空矩阵
 60 Matrix operator ^ (Matrix &base,LL pow)
 61 {
 62     if(base.r!=base.c) return Matrix();
 63     LL x=base.r;
 64     Matrix ans;
 65     ans.r=ans.c=x;
 66     for (LL i=1; i<=x; i++) ans.m[i][i]=1;
 67     while (pow)
 68     {
 69         if (pow&1) ans=ans*base;
 70         base=base*base;
 71         pow>>=1;
 72     }
 73     return ans;
 74 }
 75 LL eularPhi(LL n)
 76 {
 77     LL res=n;
 78     for(LL i=2;i*i<=n;i++)
 79     {
 80         if(n%i==0)
 81         {
 82             res=res/i*(i-1);
 83             for(;n%i==0;n/=i);
 84         }
 85     }
 86     if(n!=1) res=res/n*(n-1);
 87     return res;
 88 }
 89 //拓展欧几里得算法
 90 //求ax+by=gcd(a,b)的一组解
 91 //其他解为x=x0+kb‘,y=y0-ka‘
 92 //a‘=a/gcd(a,b),b‘=b/gcd(a,b)
 93 LL extgcd(LL a,LL b,LL &x,LL &y)
 94 {
 95     LL d=a;
 96     if(b!=0)
 97     {
 98         d=extgcd(b,a%b,y,x);
 99         y-=(a/b)*x;
100     }
101     else { x=1; y=0; }
102     return d;
103 }
104 //求逆元
105 //a和m应该互质
106 LL modInverse(LL a,LL m)
107 {
108     LL x,y;
109     extgcd(a,m,x,y);
110     return (m+x%m)%m;
111 }
112 LL f(LL x)
113 {
114     Matrix a,b;
115     a.r=1; a.c=2; a.m[1][1]=2; a.m[1][2]=1;
116     b.r=2; b.c=2; b.m[1][1]=0; b.m[1][2]=b.m[2][1]=b.m[2][2]=1;
117     return (a*(b^x)).m[1][1];
118 }
119 int main()
120 {
121 #ifdef LOCAL
122     freopen("in.txt","r",stdin);
123 #endif
124     LL n;
125     while(scanf("%lld",&n)!=EOF)
126     {
127         if(n==1)
128         {
129             printf("%d\n",2);
130             continue;
131         }
132         LL ans=0;
133         for(LL i=1;i<=sqrt(n);i++)
134             if(n%i==0)
135             {
136                 LL d=i;
137                 ans=(ans+f(d)*eularPhi(n/d))%MOD;
138                 d=n/i;
139                 if(d*d==n) continue;
140                 ans=(ans+f(d)*eularPhi(n/d))%MOD;
141             }
142         printf("%lld\n",ans*modInverse(n,MOD)%MOD);
143     }
144     return 0;
145 }
时间: 2024-10-13 12:49:57

HDU-5868 Different Circle Permutation的相关文章

hdu 5868 2016 ACM/ICPC Asia Regional Dalian Online 1001 (burnside引理 polya定理)

Different Circle Permutation Time Limit: 3000/1500 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)Total Submission(s): 208    Accepted Submission(s): 101 Problem Description You may not know this but it's a fact that Xinghai Square is

hdu 5225 Tom and permutation(回溯)

题目链接:hdu 5225 Tom and permutation #include <cstdio> #include <cstring> #include <algorithm> using namespace std; typedef long long ll; const int maxn = 100; const int mod = 1e9+7; int N, ans, V[maxn + 5], A[maxn + 5]; ll S[maxn + 5], L[m

HDU - 5225 Tom and permutation

题目大意:Tom学会了通过写程序求出一个1-n的排列的逆序对数,但他的老师给了他一个难题: 给出一个1-n的排列,求所有字典序比它小的1-n的排列的逆序对数之和. Tom一时不知道该怎么做,所以他来找你帮他解决这个问题. 因为数可能很大,答案对109+7取模. 解题思路:从1到n枚举k,表示当前要计算的排列与读入的排列前k-1项相同,而第k项不同.对于每一个k,再枚举一个t,表示当前要计算的排列的第k项是t,所以t要比读入的排列的第k项小,并且不与前k-1个数中的任意一个数相等. 那么,剩下的n

(1009) HDU 6446 Tree and Permutation(规律+树上各个点的距离和)

题意: 给一棵N个点的树,对应于一个长为N的全排列,对于排列的每个相邻数字a和b,他们的贡献是对应树上顶点a和b的路径长,求所有排列的贡献和. 分析: 经过简单的分析可以得知,全部的贡献其实相当与(这颗树上各个点的距离之和)*jichen(n-1) *2; 不相信可以举个简单的例子,或者用计算机打表可以知道: 那么如何求树上各个点的距离和呢? 可以参考这个博客:https://www.cnblogs.com/shuaihui520/p/9537214.html : 那下面的问题就相当的简单了:

HDU 5343 MZL&#39;s Circle Zhou

MZL's Circle Zhou Time Limit: 1000ms Memory Limit: 131072KB This problem will be judged on HDU. Original ID: 534364-bit integer IO format: %I64d      Java class name: Main MZL's Circle Zhou is good at solving some counting problems. One day, he comes

hdu 5343 MZL&#39;s Circle Zhou SAM

MZL's Circle Zhou 题意:给定两个长度不超过a,b(1 <= |a|,|b| <= 90000),x为a的连续子串,b为y的连续子串(x和y均可以是空串):问x+y形成的不同串的个数? 误区:开始一门心思想着求出总的可形成的字符串个数,再减去a,b中相同的子串重叠的部分:想通过连续插入a+b得到的SAM并不能获得信息:因为x,y是任意的子串,连续插入导致一定是a的后缀和b的前缀 正解:直接在计算有不同子串时,就不去计算重复的 <=>对于一个可能出现x后缀和y前缀相同

【后缀自动机】HDU 5343 MZL&#39;s Circle Zhou

通道 题意:从A,B分别取出子串X,Y,求多少种不同的X+Y 思路: 代码: #include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int MAX_N = 200007; typedef unsigned long long ll; struct SAM { int val[MAX_N], fa[MAX_N], c[26][MAX_N]; int tot,

hdu 5668 Circle 中国剩余定理

Circle Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Problem Description Satiya August is in charge of souls. He finds n souls,and lets them become a circle.He ordered them to play Joseph Games.The souls will cou

HDU 4669 Mutiples on a circle(DP)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4669 题意:给出一个长度为n的数字环A和数字m.问有多少子串(连续)使得这些子串的数字拼在一起是m的倍数? 思路:首先计算A[1]和A[n]不在一起的.这个简单,只要记录f[i][j]表示到第i个数字余数为j的个数即可,然后: 接着计算a[1]和a[n]在一起的情况. 我们首先预处理end[i]表示数字子串A[i,n]连在一起对m的余数.然后枚举i从[1,n-1],那么数字设数字串[1,i]的长度为