SSL2125 NOIP2012 模擬試題一 可可解金鑰
阿新 • • 發佈:2020-12-18
技術標籤:dp
Description
摩爾莊園裡所有的快樂都由小摩爾們一起創造,一起分享,除了莊園入口,摩爾莊園的圍牆也是由小摩爾志願者重兵把守。
這些志願者在執勤的時候是不能說話,但是相鄰小摩爾們可以手牽手進行無聲交流。為了保證執勤的秩序,規定不允許4個或更多的人聯絡在一起。
守衛莊園的小摩爾們每天數量不一。現在可可要回答出他們有多少種牽手方式,才能在他們的注目禮中,昂首挺胸步入摩爾莊園。
例如,總共有4個人,那麼可以有以下7種方式:
1,1,1,1
1,2,1
1,1,2
2,1,1
2,2
1,3
3,1
你能不能幫助可可解決這個問題呢?
Input
共一行。一個1~10000的正整數n,表示共有n個小摩爾。
Output
共一行。輸出一個正整數表示n個小摩爾牽手的方式數目。
Sample Input
4
Sample Output
7
思路
全網唯一一道該題題解系列,冷門破題(可能不久就只是第一道該題題解系列了)
謹以此題,紀念我因錯誤演算法而浪費的3天
論手玩資料錯誤的悲哀(以後還是用WPS打表吧)
該題設f[i]為i個摩爾的牽手數,則:
f
[
i
]
=
f
[
i
−
1
]
+
f
[
i
−
2
]
+
f
[
i
−
3
]
,
其
中
f
[
1
]
=
1
,
f
[
2
]
=
2
,
f
[
3
]
=
4
f[i]=f[i-1]+f[i-2]+f[i-3],其中f[1]=1,f[2]=2,f[3]=4
f[i]=f[i−1]+f[i−2]+f[i−3],其中f[1]=1,f[2]=2,f[3]=4
code:
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
short int a2[10001][3001],b[10001],n,e,p;//short出奇跡,int就MLE了
short int h(short int x)
{
memcpy(a2[x],a2[x-1],sizeof(a2[x]));
e=b[x-1];
for (int i=1;i<=e+ 3;i++)
{
p+=a2[x][i]+a2[x-2][i];
a2[x][i]=p%10;
p/=10;
}
for (int i=1;i<=e+3;i++)
{
p+=a2[x][i]+a2[x-3][i];
a2[x][i]=p%10;
p/=10;
}
e+=3;
while (e!=b[x-1]&&a2[x][e]==0) e--;
return e;
}
void print(short int x)
{
for (short int i=b[x];i>=1;i--) printf("%d",a2[x][i]);
return;
}
int main()
{
cin>>n;
a2[1][1]=1;
b[1]=1;
b[2]=1;
b[3]=1;
a2[2][1]=2;
a2[3][1]=4;//邊界
for (short int i=4;i<=n;i++) b[i]=h(i);
print(n);
return 0;
}
錯誤(TLE且可能WA的錯誤演算法)演算法:
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
string a3[40001]={"1","1"},ans="1";
int a2[40001],c[40001],b[40001],n,maxn=40001;
void mul(int b)//加減乘除應有盡有嗚嗚嗚(一個加八聚氧還t的破題)
{
memcpy(a2,c,sizeof(a2));
memset(c,0,sizeof(c));
for (int i=1;i<=40000;i++)
{
int g=0;
c[i]=a2[i]*b;
}
for (int i=1;i<=40000;i++)
{
c[i+1]+=c[i]/10;
c[i]=c[i]%10;
}
return;
}
string prit()
{
string c1="";
int i=40000;
while (i>=1&&c[i]==0) i--;
while (i>=1)
{
long long u=c[i];
char x=u%10+'0';
c1+=x;
i--;
}
return c1;
}
void scn(string x)
{
memset(c,0,sizeof(c));
for (int i=1,j=x.size()-1;j>=0;i++,j--) c[i]=x[j]-'0';
return;
}
string h(string a1,string b1)
{
int p=0;
string c1="";
memset(a2,0,sizeof(a2));
memset(b,0,sizeof(b));
int e=(a1.size()>b1.size()?a1.size():b1.size());
for (int i=0,j=a1.size()-1;j>=0;i++,j--)
{
a2[i]=a1[j]-'0';
}
for (int i=0,j=b1.size()-1;j>=0;i++,j--) b[i]=b1[j]-'0';
for (int i=0;i<=e;i++)
{
p+=a2[i]+b[i];
char x=p%10+'0'; string x2="";x2+=x;
p/=10;
c1.insert(0,x2);
}
while (c1[0]=='0') c1.erase(0,1);
return c1;
}
bool comp(int a[],int b[])
{
int i=0;
while (a[i]==b[i]&&i<maxn) i++;
if(i==maxn) return 1;
return (a[i]>=b[i]);
}
void sub()
{
int g=0;
for(int i=maxn-1;i>0;i--)
{
if (a2[i]-b[i]-g>=0)
{
a2[i]=a2[i]-b[i]-g;
g=0;
}
else
{
a2[i]=10+a2[i]-b[i]-g;
g=1;
}
}
return;
}
void add(int n)
{
int g=0;
c[n]++;
for(int i=n;i>=1;i--)
{
c[i]=c[i]+g;
g=c[i]/10;
c[i]=c[i]%10;
}
}
string work(string str1,string str2)
{
int m=0;
memset(a2,0,sizeof(a2));
memset(b,0,sizeof(b));
memset(c,0,sizeof(c));
for (int i=0;i<str1.size();i++) a2[maxn-str1.size()+i]=str1[i]-'0';
for (int i=0;i<str2.size();i++) b[maxn-str2.size()+i]=str2[i]-'0';
int j=1;
while (comp(a2,b))
{
j++;
for (int i=2;i<maxn;i++)
{
b[i-1]=b[i];
b[i]=0;
}
m=j;
}
while (j>0)
{
while (comp(a2,b))
{
add(maxn-j);
sub();
}
j--;
for (int i=maxn-1;i>=1;i--)
{
b[i]=b[i-1];
}
}
string c1="";
int i=maxn-1;
while (i>0&&c[i]=='0') i--;
while (i>0)
{
int p=c[i];
char x=p%10+'0'; string x2="";x2+=x;
p/=10;
c1.insert(0,x2);
i--;
}
while (c1[0]=='0') c1.erase(0,1);
return c1;
}
string ch(string x,int y)
{
string c1="";
int y2=y,s=0,i,j=1;
while (y2!=0)
{
y2/=10;
s++;
}
for (i=x.size()-1;j<=s;j++,i--) y2=y2*10+x[i]-'0';
if (y2<y) y2=y2*10+x[i--]-'0';
for (;i>=0;i--)
{
char xx=y2/y+'0';
c1+=xx;
y2%=y;
y2=y2*10+x[i]-'0';
}
char xx=y2/y+'0';
c1+=xx;
y2%=y;
y2=y2*10+x[i]-'0';
return c1;
}
int main()
{
cin>>n;
if (n==1)//特判
{
cout<<1;
return 0;
}
if (n==2)
{
cout<<2;
return 0;
}
if (n==3)
{
cout<<4;
return 0;
}
c[1]=1;
for (int i=2;i<n;i++) mul(i),a3[i]=prit();
string u;
int j,k;
for (int i=n-2;i>=0;i--)
{
j=(n-i)/2,k=0;//排列組合加優化
u=work(work(work(a3[i+j+k],a3[i]),a3[j]),a3[k]);
ans=h(ans,u);
scn(u);
if ((n-i)%2) j--,k++;
while (j-3>=0)
{
mul(j*(j-1)*(j-2));
u=prit();
j-=3;
u=ch(u,(k+1)*(k+2));
k+=2;
ans=h(ans,u);
}
}
cout<<ans;
return 0;
}