SSL2125 NOIP2012 模拟试题一 可可解密钥

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;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值