康拓排序各種求法
全排序與康拓展開
n=3
全排列:
123
132
213
231
312
321
每個數列由1~n組成,且出現一次。
對於第一個位置,有n種選擇,對於第二個位置,有(n-1)種選擇,…,對於最後一個位置,有1種選擇,所有共有n!種排序方法。
數列從小到大排序(或從大到小排序,或不排序))。
數列:x[n]_x[n-1]_…_x[1] (從小到大排列後為1~n)
該數列的編號:num=a[n]*(n-1)!+a[n-1]*(n-2)!+a[1]*0!
a[k]:x[k]在當前未出現的元素中排在第(a[k]+1)個
而num:0~n!-1,a[k]<=k-1。
證明:
若x[n]_x[n-1]_…_x[k+1]_(min)的起始編號為x,
則x[n]_x[n-1]_…_x[k+1]_x[k]_(min)的起始編號為x+a[k]*(k-1)!,即某一個x[k]在原來的基礎上加上a[k]*(k-1)!。
註意0!=1。因為定義C(x,y)=x!/(x-y)!/y!,而C(x,0)=x!/x!/0!=1,所以定義0!=1。
求全排序:
I.
dfs1,時間效率高,但數列並沒有排序。
#include <iostream>
#define maxn 15
using namespace std;
//每一位的確定:還未使用的數 依次被選擇(swap(a[pos],a[i]); //以a[i]作為第pos位)
//所以數列不會產生重復
//數列沒有排序!
//第pos位有1次未交換位置,(n-pos)次交換位置
//而與第pos位中的某個數延展得到的數有(n-pos)!個
//交換兩數和交換回來需要6次操作
//(n-1)!*(n-1)+(n-2)!*(n-2)+…+1!*1=n!-1
//O(6*(n!-1))=O(6n!),時間復雜度很低,創建全排序效率很高!
long a[maxn+1],n;
void swap(long &a,long &b)
{
long temp;
temp=a;
a=b;
b=temp;
}
void dfs(long pos)
{
long i;
if (pos==n)
{
for (i=1;i<=n;i++)
cout<<a[i]<<" ";
cout<<endl;
}
else
{
dfs(pos+1);
for (i=pos+1;i<=n;i++)
{
swap(a[pos],a[i]); //以a[i]作為第pos位
dfs(pos+1);
swap(a[pos],a[i]);
}
}
}
int main()
{
long i;
cin>>n;
for (i=1;i<=n;i++)
a[i]=i;
dfs(1);
return 0;
}
II.
dfs2,時間復雜度高
#include <iostream>
#define maxn 15
using namespace std;
//dfs:要是哪個數未被使用,就使用該數
//由於是按從小到大的順序判斷,所以數列也是從小到大排序
//dfs執行完後要改變為原來的狀態(回溯):vis[i]=true;(標記該數未被使用)
//dfs時間復雜度較高
long n,a[maxn+1];
bool vis[maxn+1];
void dfs(long pos)
{
long i;
if (pos==n+1)
{
for (i=1;i<=n;i++)
cout<<a[i]<<" ";
cout<<endl;
}
else
{
for (i=1;i<=n;i++)
if (vis[i])
{
vis[i]=false;
a[pos]=i;
dfs(pos+1);
vis[i]=true;
}
}
}
int main()
{
long i;
cin>>n;
for (i=1;i<=n;i++)
{
vis[i]=true;
a[i]=i;
}
dfs(1);
return 0;
}
III.
小到大排序,由第k個數推出第(k+1)個數
#include <stdio.h>
#include <stdlib.h>
#define maxn 15
//編號為k的數列通過一系列操作改變為編號為k+1的數列
int main()
{
long j,k,n,temp,x,y,a[maxn+1];
long long i,s;
scanf("%ld",&n);
//posibility
s=1;
for (i=2;i<=n;i++)
s=s*i;
for (i=1;i<=n;i++)
a[i]=i;
for (k=1;k<=n;k++)
printf("%ld ",a[k]);
printf("\n");
for (i=1;i<s;i++)
{
//4 8 7 6 5 3 2 1
//5 8 7 6 4 3 2 1
//5 1 2 3 4 6 7 8
//從尾到頭,找到第一個下降的a[j]
for (j=n-1;j>=1;j--)
if (a[j]<a[j+1])
break;
//a[j]:從尾到a[j],找到第一個比a[j]大的數a[k]
for (k=n;k>j;k--)
if (a[k]>a[j])
break;
//交換a[j]和a[k]的值
temp=a[j];
a[j]=a[k];
a[k]=temp;
//數組:j+1~n reverse
x=j+1;
y=n;
while (x<y)
{
temp=a[x];
a[x]=a[y];
a[y]=temp;
x++;
y--;
}
for (k=1;k<=n;k++)
printf("%ld ",a[k]);
printf("\n");
}
return 0;
}
IV.
康拓展開,通過數的編號逆推出數
#include <iostream>
#define maxn 15
using namespace std;
//數列:x[n]_x[n-1]_…_x[1] (從小到大排列後為1~n)
//該數列的編號:num=a[n]*(n-1)!+a[n-1]*(n-2)!+a[1]*0!
//a[k]:x[k]在當前未出現的元素中排在第(a[k]+1)個
//num:0~n!-1 a[k]<=k-1
//時間復雜度:
//尋找數列:x[n]_x[n-1]_…_x[1]
//1~x[n];1~x[n-1];…;1~x[1],總x[n]+x[n-1]+…+x[1]=1+2+…+n=n*(n+1)/2
//數列共有n!個,所以O(n*(n+1)/2*n!),這是個大概值
int main()
{
long n,value[maxn+1],i,j,k,num,pos;
bool vis[maxn+1];
cin>>n;
value[1]=1;
value[2]=1;
for (i=2;i<=n;i++)
value[i+1]=value[i]*i;
for (i=0;i<value[n+1];i++)
{
for (j=1;j<=n;j++)
vis[j]=false;
num=i;
for (j=n;j>=1;j--)
{
pos=num/value[j];
num-=pos*value[j];
//assume TTFTTTFFT
k=0;
while (pos>=0)
{
pos--;
k++;
while (vis[k])
k++;
}
vis[k]=true;
cout<<k<<" ";
}
cout<<endl;
}
return 0;
}
修改後速度提高:
#include <iostream>
#define maxn 15
using namespace std;
//數列:x[n]_x[n-1]_…_x[1] (從小到大排列後為1~n)
//該數列的編號:num=a[n]*(n-1)!+a[n-1]*(n-2)!+a[1]*0!
//a[k]:x[k]在當前未出現的元素中排在第(a[k]+1)個
//num:0~n!-1 a[k]<=k-1
//時間復雜度:
//尋找數列:x[n]_x[n-1]_…_x[1]
//找x[k]次需要a[k]次,尋找一個數列需要a[n]+a[n-1]+…+a[1]次操作
//a[k]:0~k-1出現概率相同,平均值為(k-1)/2
//所以a[n],a[n-1],…,a[1]的平均值為(n-1)/2,(n-2)/2,…,0
//數列共有n!個,所以O(((n-1)/2+(n-2)/2+…+0)*n!)=O((n-1)*n/4*n!)
//這個值是被低估的,但比上個方法快
int main()
{
long n,value[maxn+1],i,j,num,pos,next[maxn+1],s,head;
cin>>n;
value[1]=1;
value[2]=1;
for (i=2;i<=n;i++)
value[i+1]=value[i]*i;
for (i=0;i<value[n+1];i++)
{
for (j=1;j<=n;j++)
next[j]=j+1;
head=1;
num=i;
for (j=n;j>=1;j--)
{
pos=num/value[j];
num-=pos*value[j];
//assume TTFTTTFFT
if (pos==0)
{
cout<<head<<" ";
head=next[head];
}
else
{
s=head;
while (pos>1)
{
s=next[s];
pos--;
}
cout<<next[s]<<" ";
next[s]=next[next[s]];
}
}
cout<<endl;
}
return 0;
}
康拓展開求編號
s[1],s[2],…,s[n]都不相同,且{s[1],s[2],…,s[n]}={1,2,…,n}
X=(s[1],s[2],…,s[n])
Number(X)=a[n]*(n-1)!+a[n-1]*(n-2)!+...+a[1]*0!
a[i]:數s[i]比s[i+1]~s[n]大的個數或者s[i]-1 減去s[i]比s[1]~s[i-1]大的數目
(因為n個數從1~n且都不相同,比s[i]小的數有s[i]-1個)
如X=2413
Number(2413)=1*3!+2*2!+0*1!+0*0!=10
求一個數X的編號(從小到大排序,最小數的編號為0)
Code:
#include <stdio.h>
#include <stdlib.h>
#define maxn 15
int main()
{
long n,i,j,x[maxn+1],value[maxn+1],pos,ans=0;
scanf("%ld",&n);
for (i=1;i<=n;i++)
scanf("%ld",&x[i]);
//value[1]=1;
value[2]=1;
for (i=2;i<n;i++)
value[i+1]=value[i]*i;
//不用考慮最後1位,最後一位對應的值為0
for (i=1;i<n;i++)
{
pos=0;
for (j=i+1;j<=n;j++)
if (x[i]>x[j])
pos++;
ans+=pos*value[n+1-i];
}
printf("%ld\n",ans);
return 0;
}
Code:(高精度)
#include <iostream>
#include <memory.h>
using namespace std;
long max(long a,long b)
{
if (a>b)
return a;
else
return b;
}
int main()
{
long n,i,j,s[100],value[100][100],len[100],g,ans[100],lenans,c[100],lenc;
cin>>n;
for (i=1;i<=n;i++)
cin>>s[i];
value[0][1]=0;
len[1]=1;
value[1][1]=1;
len[1]=1;
for (j=2;j<n;j++)
{
value[j][1]=0;
for (i=1;i<=len[j-1];i++)
{
value[j][i]+=value[j-1][i]*j;
if (value[j][i]>=10000)
{
value[j][i+1]=value[j][i]/10000;
value[j][i]=value[j][i]%10000;
}
else
value[j][i+1]=0;
}
if (value[j][i]==0)
len[j]=len[j-1];
else
len[j]=len[j-1]+1;
}
/*
value[0]=0;
value[1]=1;
for (i=2;i<n;i++)
value[i]=value[i-1]*i;
*/
lenans=1;
memset(ans,0,sizeof(ans));
for (i=1;i<=n;i++)
{
g=0;
for (j=i+1;j<=n;j++)
if (s[i]>s[j])
g++;
//ans+=g*value[n-i];
c[1]=0;
for (j=1;j<=len[n-i];j++)
{
c[j]+=g*value[n-i][j];
if (c[j]>=10000)
{
c[j+1]=c[j]/10000;
c[j]=c[j]%10000;
}
else
c[j+1]=0;
}
if (c[j]==0)
lenc=j-1;
else
lenc=j;
lenans=max(lenans,lenc);
for (j=1;j<=lenans;j++)
{
ans[j]+=c[j];
if (ans[j]>=10000)
{
ans[j+1]++;
ans[j]-=10000;
}
}
if (ans[j]!=0)
lenans++;
}
//cout<<ans<<endl;
cout<<ans[lenans];
for (i=lenans-1;i>=1;i--)
if (ans[i]>=1000)
cout<<ans[i];
else if (ans[i]>=100)
cout<<"0"<<ans[i];
else if (ans[i]>=10)
cout<<"00"<<ans[i];
else
cout<<"000"<<ans[i];
cout<<endl;
return 0;
}
#include <stdio.h>
#include <stdlib.h>
#define maxn 100
#define maxw 100
#define div 10000
int main()
{
long n,pos,i,j,x[maxn+1],value[maxn+1][maxw+1],len[maxn+1],ans[maxw+1],lenans,s[maxw+1],lens;
scanf("%ld",&n);
for (i=1;i<=n;i++)
scanf("%ld",&x[i]);
value[2][1]=1;
len[2]=1;
//高+/*低 低<除數,最多進1位
for (i=2;i<n;i++)
{
value[i+1][0]=0;
for (j=1;j<=len[i];j++)
{
value[i+1][j]=value[i][j]*i+value[i+1][j-1]/div;
value[i+1][j-1]=value[i+1][j-1]%div;
}
if (value[i+1][j-1]>=div)
{
value[i+1][j]=value[i+1][j-1]/div;
value[i+1][j-1]=value[i+1][j-1]%div;
len[i+1]=j;
}
else
len[i+1]=j-1;
}
// for (i=2;i<n;i++)
// value[i+1]=value[i]*i;
//不用考慮最後1位,最後一位對應的值為0
for (i=1;i<=maxw;i++)
ans[i]=0;
lenans=1;
s[0]=0;
for (i=1;i<n;i++)
{
pos=0;
for (j=i+1;j<=n;j++)
if (x[i]>x[j])
pos++;
for (j=1;j<=len[n+1-i];j++)
{
s[j]=value[n+1-i][j]*pos+s[j-1]/div;
s[j-1]=s[j-1]%div;
}
if (s[j-1]>=div)
{
s[j]=s[j-1]/div;
s[j-1]=s[j-1]%div;
lens=j;
}
else
lens=j-1;
for (j=1;j<=lens;j++)
{
ans[j]+=s[j];
if (ans[j]>=div)
{
ans[j+1]++;
ans[j]-=div;
}
}
if (ans[lenans+1]!=0)
lenans++;
// ans+=pos*value[n+1-i];
}
printf("%ld",ans[lenans]);
for (i=lenans-1;i>=1;i--)
if (ans[i]>=1000)
printf("%ld",ans[i]);
else if (ans[i]>=100)
printf("0%ld",ans[i]);
else if (ans[i]>=10)
printf("00%ld",ans[i]);
else
printf("000%ld",ans[i]);
printf("\n");
return 0;
}
Input:
100
100 99 98 97 96 95 94 93 92 91 90 89 88 87 86 85 84 83 82 81 80 79 78 77 76 75 74 73 72 71 70 69 68 67 66 65 64 63 62 61
60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 31 30 29 28 27 26 25 24 23 22 21
20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1
Output:
93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916863999999999999999999999999
全排序與康拓展開
n=3
全排列:
123
132
213
231
312
321
每個數列由1~n組成,且出現一次。
對於第一個位置,有n種選擇,對於第二個位置,有(n-1)種選擇,…,對於最後一個位置,有1種選擇,所有共有n!種排序方法。
數列從小到大排序(或從大到小排序,或不排序))。
數列:x[n]_x[n-1]_…_x[1] (從小到大排列後為1~n)
該數列的編號:num=a[n]*(n-1)!+a[n-1]*(n-2)!+a[1]*0!
a[k]:x[k]在當前未出現的元素中排在第(a[k]+1)個
而num:0~n!-1,a[k]<=k-1。
證明:
若x[n]_x[n-1]_…_x[k+1]_(min)的起始編號為x,
則x[n]_x[n-1]_…_x[k+1]_x[k]_(min)的起始編號為x+a[k]*(k-1)!,即某一個x[k]在原來的基礎上加上a[k]*(k-1)!。
註意0!=1。因為定義C(x,y)=x!/(x-y)!/y!,而C(x,0)=x!/x!/0!=1,所以定義0!=1。
求全排序:
I.
dfs1,時間效率高,但數列並沒有排序。
#include <iostream>
#define maxn 15
using namespace std;
//每一位的確定:還未使用的數 依次被選擇(swap(a[pos],a[i]); //以a[i]作為第pos位)
//所以數列不會產生重復
//數列沒有排序!
//第pos位有1次未交換位置,(n-pos)次交換位置
//而與第pos位中的某個數延展得到的數有(n-pos)!個
//交換兩數和交換回來需要6次操作
//(n-1)!*(n-1)+(n-2)!*(n-2)+…+1!*1=n!-1
//O(6*(n!-1))=O(6n!),時間復雜度很低,創建全排序效率很高!
long a[maxn+1],n;
void swap(long &a,long &b)
{
long temp;
temp=a;
a=b;
b=temp;
}
void dfs(long pos)
{
long i;
if (pos==n)
{
for (i=1;i<=n;i++)
cout<<a[i]<<" ";
cout<<endl;
}
else
{
dfs(pos+1);
for (i=pos+1;i<=n;i++)
{
swap(a[pos],a[i]); //以a[i]作為第pos位
dfs(pos+1);
swap(a[pos],a[i]);
}
}
}
int main()
{
long i;
cin>>n;
for (i=1;i<=n;i++)
a[i]=i;
dfs(1);
return 0;
}
II.
dfs2,時間復雜度高
#include <iostream>
#define maxn 15
using namespace std;
//dfs:要是哪個數未被使用,就使用該數
//由於是按從小到大的順序判斷,所以數列也是從小到大排序
//dfs執行完後要改變為原來的狀態(回溯):vis[i]=true;(標記該數未被使用)
//dfs時間復雜度較高
long n,a[maxn+1];
bool vis[maxn+1];
void dfs(long pos)
{
long i;
if (pos==n+1)
{
for (i=1;i<=n;i++)
cout<<a[i]<<" ";
cout<<endl;
}
else
{
for (i=1;i<=n;i++)
if (vis[i])
{
vis[i]=false;
a[pos]=i;
dfs(pos+1);
vis[i]=true;
}
}
}
int main()
{
long i;
cin>>n;
for (i=1;i<=n;i++)
{
vis[i]=true;
a[i]=i;
}
dfs(1);
return 0;
}
III.
小到大排序,由第k個數推出第(k+1)個數
#include <stdio.h>
#include <stdlib.h>
#define maxn 15
//編號為k的數列通過一系列操作改變為編號為k+1的數列
int main()
{
long j,k,n,temp,x,y,a[maxn+1];
long long i,s;
scanf("%ld",&n);
//posibility
s=1;
for (i=2;i<=n;i++)
s=s*i;
for (i=1;i<=n;i++)
a[i]=i;
for (k=1;k<=n;k++)
printf("%ld ",a[k]);
printf("\n");
for (i=1;i<s;i++)
{
//4 8 7 6 5 3 2 1
//5 8 7 6 4 3 2 1
//5 1 2 3 4 6 7 8
//從尾到頭,找到第一個下降的a[j]
for (j=n-1;j>=1;j--)
if (a[j]<a[j+1])
break;
//a[j]:從尾到a[j],找到第一個比a[j]大的數a[k]
for (k=n;k>j;k--)
if (a[k]>a[j])
break;
//交換a[j]和a[k]的值
temp=a[j];
a[j]=a[k];
a[k]=temp;
//數組:j+1~n reverse
x=j+1;
y=n;
while (x<y)
{
temp=a[x];
a[x]=a[y];
a[y]=temp;
x++;
y--;
}
for (k=1;k<=n;k++)
printf("%ld ",a[k]);
printf("\n");
}
return 0;
}
IV.
康拓展開,通過數的編號逆推出數
#include <iostream>
#define maxn 15
using namespace std;
//數列:x[n]_x[n-1]_…_x[1] (從小到大排列後為1~n)
//該數列的編號:num=a[n]*(n-1)!+a[n-1]*(n-2)!+a[1]*0!
//a[k]:x[k]在當前未出現的元素中排在第(a[k]+1)個
//num:0~n!-1 a[k]<=k-1
//時間復雜度:
//尋找數列:x[n]_x[n-1]_…_x[1]
//1~x[n];1~x[n-1];…;1~x[1],總x[n]+x[n-1]+…+x[1]=1+2+…+n=n*(n+1)/2
//數列共有n!個,所以O(n*(n+1)/2*n!),這是個大概值
int main()
{
long n,value[maxn+1],i,j,k,num,pos;
bool vis[maxn+1];
cin>>n;
value[1]=1;
value[2]=1;
for (i=2;i<=n;i++)
value[i+1]=value[i]*i;
for (i=0;i<value[n+1];i++)
{
for (j=1;j<=n;j++)
vis[j]=false;
num=i;
for (j=n;j>=1;j--)
{
pos=num/value[j];
num-=pos*value[j];
//assume TTFTTTFFT
k=0;
while (pos>=0)
{
pos--;
k++;
while (vis[k])
k++;
}
vis[k]=true;
cout<<k<<" ";
}
cout<<endl;
}
return 0;
}
修改後速度提高:
#include <iostream>
#define maxn 15
using namespace std;
//數列:x[n]_x[n-1]_…_x[1] (從小到大排列後為1~n)
//該數列的編號:num=a[n]*(n-1)!+a[n-1]*(n-2)!+a[1]*0!
//a[k]:x[k]在當前未出現的元素中排在第(a[k]+1)個
//num:0~n!-1 a[k]<=k-1
//時間復雜度:
//尋找數列:x[n]_x[n-1]_…_x[1]
//找x[k]次需要a[k]次,尋找一個數列需要a[n]+a[n-1]+…+a[1]次操作
//a[k]:0~k-1出現概率相同,平均值為(k-1)/2
//所以a[n],a[n-1],…,a[1]的平均值為(n-1)/2,(n-2)/2,…,0
//數列共有n!個,所以O(((n-1)/2+(n-2)/2+…+0)*n!)=O((n-1)*n/4*n!)
//這個值是被低估的,但比上個方法快
int main()
{
long n,value[maxn+1],i,j,num,pos,next[maxn+1],s,head;
cin>>n;
value[1]=1;
value[2]=1;
for (i=2;i<=n;i++)
value[i+1]=value[i]*i;
for (i=0;i<value[n+1];i++)
{
for (j=1;j<=n;j++)
next[j]=j+1;
head=1;
num=i;
for (j=n;j>=1;j--)
{
pos=num/value[j];
num-=pos*value[j];
//assume TTFTTTFFT
if (pos==0)
{
cout<<head<<" ";
head=next[head];
}
else
{
s=head;
while (pos>1)
{
s=next[s];
pos--;
}
cout<<next[s]<<" ";
next[s]=next[next[s]];
}
}
cout<<endl;
}
return 0;
}
康拓展開求編號
s[1],s[2],…,s[n]都不相同,且{s[1],s[2],…,s[n]}={1,2,…,n}
X=(s[1],s[2],…,s[n])
Number(X)=a[n]*(n-1)!+a[n-1]*(n-2)!+...+a[1]*0!
a[i]:數s[i]比s[i+1]~s[n]大的個數或者s[i]-1 減去s[i]比s[1]~s[i-1]大的數目
(因為n個數從1~n且都不相同,比s[i]小的數有s[i]-1個)
如X=2413
Number(2413)=1*3!+2*2!+0*1!+0*0!=10
求一個數X的編號(從小到大排序,最小數的編號為0)
Code:
#include <stdio.h>
#include <stdlib.h>
#define maxn 15
int main()
{
long n,i,j,x[maxn+1],value[maxn+1],pos,ans=0;
scanf("%ld",&n);
for (i=1;i<=n;i++)
scanf("%ld",&x[i]);
//value[1]=1;
value[2]=1;
for (i=2;i<n;i++)
value[i+1]=value[i]*i;
//不用考慮最後1位,最後一位對應的值為0
for (i=1;i<n;i++)
{
pos=0;
for (j=i+1;j<=n;j++)
if (x[i]>x[j])
pos++;
ans+=pos*value[n+1-i];
}
printf("%ld\n",ans);
return 0;
}
Code:(高精度)
#include <iostream>
#include <memory.h>
using namespace std;
long max(long a,long b)
{
if (a>b)
return a;
else
return b;
}
int main()
{
long n,i,j,s[100],value[100][100],len[100],g,ans[100],lenans,c[100],lenc;
cin>>n;
for (i=1;i<=n;i++)
cin>>s[i];
value[0][1]=0;
len[1]=1;
value[1][1]=1;
len[1]=1;
for (j=2;j<n;j++)
{
value[j][1]=0;
for (i=1;i<=len[j-1];i++)
{
value[j][i]+=value[j-1][i]*j;
if (value[j][i]>=10000)
{
value[j][i+1]=value[j][i]/10000;
value[j][i]=value[j][i]%10000;
}
else
value[j][i+1]=0;
}
if (value[j][i]==0)
len[j]=len[j-1];
else
len[j]=len[j-1]+1;
}
/*
value[0]=0;
value[1]=1;
for (i=2;i<n;i++)
value[i]=value[i-1]*i;
*/
lenans=1;
memset(ans,0,sizeof(ans));
for (i=1;i<=n;i++)
{
g=0;
for (j=i+1;j<=n;j++)
if (s[i]>s[j])
g++;
//ans+=g*value[n-i];
c[1]=0;
for (j=1;j<=len[n-i];j++)
{
c[j]+=g*value[n-i][j];
if (c[j]>=10000)
{
c[j+1]=c[j]/10000;
c[j]=c[j]%10000;
}
else
c[j+1]=0;
}
if (c[j]==0)
lenc=j-1;
else
lenc=j;
lenans=max(lenans,lenc);
for (j=1;j<=lenans;j++)
{
ans[j]+=c[j];
if (ans[j]>=10000)
{
ans[j+1]++;
ans[j]-=10000;
}
}
if (ans[j]!=0)
lenans++;
}
//cout<<ans<<endl;
cout<<ans[lenans];
for (i=lenans-1;i>=1;i--)
if (ans[i]>=1000)
cout<<ans[i];
else if (ans[i]>=100)
cout<<"0"<<ans[i];
else if (ans[i]>=10)
cout<<"00"<<ans[i];
else
cout<<"000"<<ans[i];
cout<<endl;
return 0;
}
#include <stdio.h>
#include <stdlib.h>
#define maxn 100
#define maxw 100
#define div 10000
int main()
{
long n,pos,i,j,x[maxn+1],value[maxn+1][maxw+1],len[maxn+1],ans[maxw+1],lenans,s[maxw+1],lens;
scanf("%ld",&n);
for (i=1;i<=n;i++)
scanf("%ld",&x[i]);
value[2][1]=1;
len[2]=1;
//高+/*低 低<除數,最多進1位
for (i=2;i<n;i++)
{
value[i+1][0]=0;
for (j=1;j<=len[i];j++)
{
value[i+1][j]=value[i][j]*i+value[i+1][j-1]/div;
value[i+1][j-1]=value[i+1][j-1]%div;
}
if (value[i+1][j-1]>=div)
{
value[i+1][j]=value[i+1][j-1]/div;
value[i+1][j-1]=value[i+1][j-1]%div;
len[i+1]=j;
}
else
len[i+1]=j-1;
}
// for (i=2;i<n;i++)
// value[i+1]=value[i]*i;
//不用考慮最後1位,最後一位對應的值為0
for (i=1;i<=maxw;i++)
ans[i]=0;
lenans=1;
s[0]=0;
for (i=1;i<n;i++)
{
pos=0;
for (j=i+1;j<=n;j++)
if (x[i]>x[j])
pos++;
for (j=1;j<=len[n+1-i];j++)
{
s[j]=value[n+1-i][j]*pos+s[j-1]/div;
s[j-1]=s[j-1]%div;
}
if (s[j-1]>=div)
{
s[j]=s[j-1]/div;
s[j-1]=s[j-1]%div;
lens=j;
}
else
lens=j-1;
for (j=1;j<=lens;j++)
{
ans[j]+=s[j];
if (ans[j]>=div)
{
ans[j+1]++;
ans[j]-=div;
}
}
if (ans[lenans+1]!=0)
lenans++;
// ans+=pos*value[n+1-i];
}
printf("%ld",ans[lenans]);
for (i=lenans-1;i>=1;i--)
if (ans[i]>=1000)
printf("%ld",ans[i]);
else if (ans[i]>=100)
printf("0%ld",ans[i]);
else if (ans[i]>=10)
printf("00%ld",ans[i]);
else
printf("000%ld",ans[i]);
printf("\n");
return 0;
}
Input:
100
100 99 98 97 96 95 94 93 92 91 90 89 88 87 86 85 84 83 82 81 80 79 78 77 76 75 74 73 72 71 70 69 68 67 66 65 64 63 62 61
60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 31 30 29 28 27 26 25 24 23 22 21
20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1
Output:
93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916863999999999999999999999999
康拓排序各種求法