2 条题解
-
0
坏了,这一下真给我难道了。(题目标签应该加一个数学)
这题最为关键的就是发现这么一个性质:给出的棋盘其实根本不重要,既然任意两个棋子不在同一行也不在同一列,那我们完全就可以把整个棋盘打乱重拍,强制令第 行的障碍在第 列,那么原问题就变成了如下问题:
求出有多少个排列,使得第 个位置不能为 。
这是一个经典的错排问题,我们定义 为前 个数的放置方案,显然,对于第 个数而言,除了 都能放,所以有 种可能。假设其放在了位置 上,则 可以放在 上,此时转化为 ,也可以放在别的位置上,此时转化为 ,递推公式就是:
最后写个高精度就可以了。
代码:
#include<bits/stdc++.h> using namespace std; struct num{//高精度 string nu; num operator +(const num &ano)const{ string a=nu,b=ano.nu; if(a.size()>b.size())swap(a,b); int l1=a.size(),l2=b.size(); // 0 1 2 3 l1=4 //0 1 2 3 4 l2=5 string ans; int ji=0; for(int i=l2-1;i>=l2-l1;i--){ ans=char((a[i-l2+l1]-'0'+b[i]-'0'+ji)%10+'0')+ans; ji=(a[i-l2+l1]-'0'+b[i]-'0'+ji)/10; } for(int i=l2-l1-1;i>=0;i--){ ans=char((b[i]-'0'+ji)%10+'0')+ans; ji=(b[i]-'0'+ji)/10; } if(ji)ans='1'+ans; return (num){ans}; } num operator *(const int &ano)const{ int ji=0; string ans; for(int i=nu.size()-1;i>=0;i--){ ans=char(((nu[i]-'0')*ano+ji)%10+'0')+ans; ji=((nu[i]-'0')*ano+ji)/10; } if(ji){ ans=to_string(ji)+ans; } return (num){ans}; } }; num dp[205]; int main(){ int n; cin>>n; dp[1].nu="0",dp[2].nu="1"; for(int i=3;i<=n;i++){ dp[i]=(dp[i-1]+dp[i-2])*(i-1); } cout<<dp[n].nu; return 0; } -
0
#include<bits/stdc++.h>//qkw using namespace std; //#define int long long struct node { int a[1010],len; node() { len=1; memset(a,0,sizeof(a)); } }; node dp[210]; node operator+(node n1,node n2) { node no;no.len=max(n1.len,n2.len); for(int i=1;i<=no.len;i++)no.a[i]=n1.a[i]+n2.a[i]; for(int i=1;i<=no.len;i++)no.a[i+1]+=no.a[i]/10,no.a[i]%=10; int i=no.len; while(no.a[i+1]>0) { i++; no.a[i+1]+=no.a[i]/10; no.a[i]%=10; } while(no.a[i]==0&&i>1)i--; no.len=i; return no; } node operator-(node n1,node n2)//默认n1比n2大 { node no; no.len=n1.len; for(int i=1;i<=no.len;i++) no.a[i]=n1.a[i]-n2.a[i]; for(int i=1;i<=no.len;i++)if(no.a[i]<0)no.a[i+1]--,no.a[i]+=10; int i=no.len; while(no.a[i+1]>0) { i++; no.a[i+1]+=no.a[i]/10; no.a[i]%=10; } while( (no.a[i]==0) && (i>1)) i--; no.len=i; return no; } node operator*(node n1,int x) { node no; no.len=n1.len; for(int i=1;i<=no.len;i++) no.a[i]=n1.a[i]*x; for(int i=1;i<=no.len;i++) { no.a[i+1]+=no.a[i]/10; no.a[i]%=10; } int i=no.len; while(no.a[i+1]>0) { i++; no.a[i+1]+=no.a[i]/10; no.a[i]%=10; } while((no.a[i]==0) && (i>1)) i--; no.len=i; return no; } signed main() { int n;cin>>n; dp[2].a[1]=1; for(int i=3;i<=n;i++) { dp[i]=dp[i-1]*i; node sum;sum.a[1]=1; if(i%2)dp[i]=dp[i]-sum; else dp[i]=dp[i]+sum; } for(int i=dp[n].len;i>=1;i--)printf("%d",dp[n].a[i]); return 0; }
- 1
信息
- ID
- 6228
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 8
- 标签
- 递交数
- 109
- 已通过
- 19
- 上传者