排列組合
生成1~n的排列:
void solve(int n, int *a, int num)///solve(n,mem,0),輸入n,按字典序從小到大的順序輸出前n個數的所有排列
{
if(num == n)///遞歸邊界
{
for(int i = 0; i < n - 1; i++)
printf("%d ",a[i]);
printf("%d\n",a[n-1]);
}
else
{
for(int i = 1; i <= n; i++)///在a[num]中遍歷一遍所有數
{
int ok = 0;
for(int j = 0; j < num; j++)
{
if(a[j] == i)///判斷a[0]~a[num-1]是否出現過該數字,出現標記爲1
ok = 1;
}
if(!ok)
{
a[num] = i;
solve(n,a,num+1);
}
}
}
return;
}
生成可重集的排列:
#include <bits/stdc++.h>
using namespace std;
const int Max = 100000 + 10;
int mem[Max], q[Max];
void solve(int n, int *p, int *a, int num)///輸入數組q,並按字典序從小到大的順序輸出數組a各元素的所有全排列
{
if(num == n)///遞歸邊界
{
for(int i = 0; i < n - 1; i++)
printf("%d ",a[i]);
printf("%d\n",a[n-1]);
}
else
{
for(int i = 0; i < n; i++)///在a[num]中遍歷一遍p數組中所有的數
{
int bj1 = 0, bj2 = 0;
if(!i || p[i] != p[i-1])///避免重複
{
for(int j = 0; j < num; j++) if(a[j] == p[i]) bj1++;;
for(int j = 0; j < n; j++) if(p[i] == p[j]) bj2++;
if(bj1 < bj2)///避免遺漏
{
a[num] = p[i];
solve(n,p,a,num+1);
}
}
}
}
return;
}
int main()
{
int n;
while (~scanf("%d",&n))
{
for(int i = 0; i < n; i++)
scanf("%d",&q[i]);
sort(q,q+n);
solve(n,q,mem,0);
}
return 0;
}
next_permutation排列函數
#include <bits/stdc++.h>
using namespace std;
const int Max = 100000 + 10;
int n, mem[Max];
void solve_int()///int 類型的 next_permutation 使用
{
for(int i = 0; i < n; i++)
scanf("%d",&mem[i]);
sort(mem,mem+n);
do
{
for(int i = 0; i < n - 1; i++)
printf("%d ",mem[i]);
printf("%d\n",mem[n-1]);
}while(next_permutation(mem,mem+n));
}
void solve_char()///char 類型的 next_permutation 使用
{
int len;
char ch[Max];
scanf("%s",ch);
len = strlen(ch);
sort(ch,ch+len);
do
{
printf("%s\n",ch);
}while(next_permutation(ch,ch+len));
}
void solve_string()///string 類型的 next_permutation 使用
{
string str;
while(cin >> str && str != "*")
{
sort(str.begin(),str.end());
do
{
cout << str << endl;
}
while(next_permutation(str.begin(),str.end()));
}
}
bool cmp(char a, char b)///自定義排序順序,'A' < 'a' < 'B' < 'b' ... < 'Z' < 'z'
{
if(tolower(a) == tolower(b))
return a < b;
else
return tolower(a) < tolower(b);
}
void solve_mem()///自定義排序方法後 next_permutation 的使用
{
int len;
char ch[Max];
scanf("%s",ch);
len = strlen(ch);
sort(ch,ch+len,cmp);
do
{
printf("%s\n",ch);
}while(next_permutation(ch,ch+len,cmp));
}
int main ()
{
scanf("%d", &n);
solve_int();
solve_char();
solve_string();
solve_mem();
return 0;
}
容斥原理
#include <bits/stdc++.h>
using namespace std;
int prime[40000], m;
bool f[40000];
vector<int>p;///存放質因數
int init()///用篩法40000以內的質數
{
m = 0;
for(int i = 2; i < 40000; i++)
{
if (f[i] == 0)
prime[m++] = i;//質數
for(int j = 0; j < m && i * prime[j] < 40000; j++)
{
f[i*prime[j]] = 1;
if(i%prime[j] == 0)
break;
}
}
}
void factor(int n)///對n分解質因數
{
p.clear();
for(int i = 0; i < m && prime[i] * prime[i] <= n; i++)
{
if(n % prime[i] == 0)
{
p.push_back(prime[i]);
n /= prime[i];
while(n % prime[i] == 0)
n /= prime[i];
}
}
if(n > 1)
p.push_back(n);
}
int solve(int r)///用二進制實現容斥原理,求區間[1,r]內與n互素的數的個數
{
int sum = 0;
for (int i = 1; i < ( 1 << p.size()); ++i)
{
int mult = 1, bits = 0;
for (int j = 0; j < p.size(); ++j)
if(i & (1 << j))
{
bits++;///計算i中1的個數,也就是質因數的個數
mult *= p[j];
}
int cur = r / mult;
if(bits & 1)///若1的個數是奇數則進行加法,否則進行減法
sum += cur;
else sum -= cur;
}
return r - sum;
}
int main()
{
init();
int n, r;
while(cin >> n >> r)
{
factor(n);
cout<<solve(r)<<endl;
}
return 0;
}
Polya計數
int gcd(int a, int b)
{
return b == 0 ? a : gcd(b,a % b);
}
ll pow(ll a, ll b)
{
ll flag = 1;
while(b--)
{
flag *= a;
}
return flag;
}
ll polya(ll n, ll m)///用m種顏色對n個珠子構成的環上色,旋轉翻轉後相同的只算一種
{
ll ans = 0;
for(ll i = 0; i < n; i++)
ans += pow(m,gcd(n,i));
if(n & 1)
ans += n * pow(m,(n-1)/2+1);
else
ans += (n/2) * pow(m,n/2) + (n/2) * pow(m,n/2+1);
return ans/(2*n);
}
Burnside定理
void solve(int z)///計算z個數中每個數的循環節長度
{
for(int i = 1; i <= z; i++)
{
int j = num[i];
int l = 1;
while(i != j)
{
l++;
j = num[j];
}
mem[i] = l;
}
}
const int MAX=1001;
int n,perm[MAX], visit[MAX];
void Polya()///sum求循環節個數,Perm用來存儲置換,即一個排列
{
int pos,sum=0;
memset(visit,0,sizeof(visit));
for(int i = 0; i < n; i++)
{
if(!visit[i])
{
sum++;
pos = i;
for(int j = 0; !visit[perm[pos]]; j++)
{
pos = perm[pos];
visit[pos] = 1;
}
}
}
return sum;
}