Online JudgeProblem SetAuthorsOnline ContestsUser
Web Board
Home Page
F.A.Qs
Statistical Charts
Problems
Submit Problem
Online Status
Prob.ID:
Register
Update your info
Authors ranklist
Current Contest
Past Contests
Scheduled Contests
Award Contest
User ID:
Password:
  Register

不打表(但保存中间计算结果),不用约瑟夫公式,优化计算过程AC。144K,47MS,700B。C实现。

Posted by lachening at 2011-04-19 19:36:27 on Problem 1012
终于过了…… 
看到有直接算出结果打表作弊的。鄙视之。
看到有套用约瑟夫递推公式的。都是一个套路:
              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:
User ID:
Password:
Title:

Content:

Home Page   Go Back  To top


All Rights Reserved 2003-2013 Ying Fuchen,Xu Pengcheng,Xie Di
Any problem, Please Contact Administrator