2018年10月31日提高組 T1 A
阿新 • • 發佈:2018-12-18
大意
求的排列了交換為升序的最小交換次數的期望
思路
兩種思路
- 暴力打表找規律
- 動態規劃
第一種只需要打一個+找出規律即可,參考程式碼:
#include<cstdio>
#include<queue>
#define p 10000007
using namespace std;int n,ans;
struct node{int a[11],bs;}begin;
struct hash
{
long long h[p];
inline int find(long long x)
{
int y= x%p;
while(h[y]&&h[y]!=x) (y+=1)%=p;
return y;
}
inline void push(node x)
{
long long t=0;
for(register int i=1;i<=n;i++) t=(t<<3)+(t<<1)+x.a[i];
h[find(t)]=t;
return;
}
inline bool check(node x)
{
long long t=0;
for(register int i=1;i<=n;i++ ) t=(t<<3)+(t<<1)+x.a[i];
return h[find(t)]==t;
}
}h;
inline void bfs()
{
queue<node>q;
q.push(begin);h.push(begin);
while(q.size())
{
node x=q.front();q.pop();
for(register int i=1;i<n;i++)
for(register int j=i+1;j<=n;j++)
{
node y=x;
swap (y.a[i],y.a[j]);
y.bs=x.bs+1;
if(!h.check(y))
{
h.push(y);
q.push(y);
ans+=y.bs;
}
}
}
return;
}
signed main()
{
scanf("%d",&n);begin.bs=0;
for(register int i=1;i<=n;i++) begin.a[i]=i;
bfs();
printf("%d",ans);
}
第二種思路也很明顯,除了最後是其它所有的交換次數都會變多
程式碼
#include<cstdio>
#include<cstring>
#include<algorithm>
#define wyc 998244353
using namespace std;
long long a[10000001],jc,inv[10000001],n,t;
inline long long ksm(long long x,long long y)
{
long long ans;
for(ans=1;y;(x*=x)%=wyc,y>>=1) if(y&1)(ans*=x)%=wyc;
return ans;
}
inline long long read()
{
char c;int f=0;
while(c=getchar(),c<48||c>57);f=(f<<3)+(f<<1)+c-48;
while(c=getchar(),c>47&&c<58) f=(f<<3)+(f<<1)+c-48;
return f;
}
inline void write(long long x){if(x>9)write(x/10);putchar(x%10+48);return;}
signed main()
{
a[1]=0;a[2]=1;jc=2;inv[0]=inv[1]=1;inv[2]=2;
for(register int i=3;i<=10000000;i++)
{
a[i]=(a[i-1]*i%wyc+(i-1)*jc%wyc)%wyc;
(jc*=i)%=wyc;
(inv[i]=inv[i-1]*i)%=wyc;
}
t=read();
while(t--)
{
n=read();
write((a[n]*ksm(inv[n],wyc-2))%wyc);putchar(10);
}
}