| ||||||||||
| Online Judge | Problem Set | Authors | Online Contests | User | ||||||
|---|---|---|---|---|---|---|---|---|---|---|
| Web Board Home Page F.A.Qs Statistical Charts | Current Contest Past Contests Scheduled Contests Award Contest | |||||||||
不打表(但保存中间计算结果),不用约瑟夫公式,优化计算过程AC。144K,47MS,700B。C实现。终于过了……
看到有直接算出结果打表作弊的。鄙视之。
看到有套用约瑟夫递推公式的。都是一个套路:
for循环用公式计算1至13的值,填表table[13];
while(输入)
{ 查表输出}
我觉得如果自己来推导计算方法能比较好,所以自己
设计计算步骤,从k=13一分钟出结果,到10s,到最后瞬间。
以下是本人代码· C实现。
觉得m值的递增可以再优化一下,不过没有找到方法。
如果m取的测试值能优化,估计不保存计算结果也能AC的。
=======================================
#include <stdio.h> 请勿直接提交该代码
char prs[27];
char killed;杀掉的人数
int table[13]={0}; 保存结果
int n,i,m,count,plus,cmpli;
int main ()
{
while( scanf("%d",&n)!=EOF && n!=0)
{
if(table[n-1]!=0)
{
printf("%d\n",table[n-1]);
continue;
}
for(i=0;i<n;i++)
prs[i]=1;
for(i=n;i<2*n;i++)
prs[i]=-1;
初始化prs[i]中的值,1是好人,-1是坏人,0是不存在,查找过程中不会修改到其中的值,因此每个CASE只设置一遍。
killed=0;
m=n+1;
plus=0; 控制量,实现m以 k+1的倍数和其倍数+1交替递增
while(killed<n)
{
killed=0;
count为当前次数,
for( count=1 ;killed<n; )
{
for循环中是此代码的核心算法,推导了一下午。
if((m-count)%(2*n-killed)>=n)
{
条件成立表示杀的是坏人,否则为好人,跳出
count=2*n-killed- (m-count)%(2*n-killed);
计算当次杀完坏人后,下轮循环开始的坏人数
killed++;
killed++导致有效数组的最后一个被排除在外,等效于杀死
}
else
break;
}
if(killed==n)
{
printf("%d\n",m);
table[n-1]=m;
注意,我是每次计算完后才存表,不是先算出13个数再填表。
break;
}
m+=plus*n+!plus;
plus=!plus;
以上两句是m的控制方法,plus值0、1切换,如从n=5,m=6,plus=0开始,得到的值依次是:6.7.12.13.18.19.24........
}
}
return 0;
}
Followed by:
Post your reply here: |
All Rights Reserved 2003-2013 Ying Fuchen,Xu Pengcheng,Xie Di
Any problem, Please Contact Administrator