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