1. 程式人生 > 其它 >SSL2125 NOIP2012 模擬試題一 可可解金鑰

SSL2125 NOIP2012 模擬試題一 可可解金鑰

技術標籤: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

思路

全網唯一一道該題題解系列,冷門破題(可能不久就只是第一道該題題解系列了)
謹以此題,紀念我因錯誤演算法而浪費的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[i1]+f[i2]+f[i3],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;
}