P1095约瑟夫问题10E100版
今天正在疯狂搬运时遇到的一道题,
以为是一道水题,仔细一看,好家伙,高精度(100位)
不能模拟去做,只能尝试用数学方法。
。。。推演后发现,一个N的圈子,可以将其划分为N/2,和N-N/2的两个小圆圈,而N的约瑟夫数为
两个小圈约瑟夫数之和再-1。
然后,就是大精度的除法和减法。
配合后,binary函数中10^100/2^M,M远远大于300次,直接爆栈。
无可奈何,只过了3个点。
但是把这次程序放上来,纪念一下吧。
<一>、对约瑟夫问题求解
#include<stdio.h>
#include<stdbool.h>
#define MAX 100005
int main()
{
int N;
int a[MAX];
bool visit[MAX];
int i;
int sum=0;
int flag=1;
scanf("%d",&N);
for(i=1;i<=N;i++)
{
a[i]=i;
visit[i]=false;
}
i=1;
while(sum!=N-1)
{
if(i>N)
i=1;
if(visit[i])
{
i++;
continue;
}
else
{
if(flag)
{
flag^=1;
i++;
}
else
{
visit[i++]=true;
flag^=1;
sum++;
}
}
}
for(i=1;i<=N;i++)
if(!visit[i])
{
printf("%d",i);
return 0;
}
return 0;
}
<二>、对高精度数的划分
//高精度除法与减法(对二除法)
#include<stdio.h>
#include<string.h>
int main()
{
char s[105];
char s1[100];
char p1[105];
char p2[105];
int i;
gets(s);
strcpy(s1,s);
for(i=0;i<=strlen(s)-1;i++)
{
p1[i]=(s[i]-'0')/2+'0';
if((s[i]-'0')%2!=0&&i!=strlen(s)-1)
s[i+1]+=10;
}
p1[i]='\0';
for(i=strlen(s1)-1;i>=0;i--)
{
if(s1[i]>=p1[i])
p2[i]=s1[i]-p1[i]+'0';
else
{
s1[i-1]--;
s1[i]+=10;
p2[i]=s1[i]-p1[i]+'0';
}
}
p2[strlen(s1)]='\0';
puts(p1);
puts(p2);
return 0;
}
<三>、合并
#include<stdio.h>
#include<stdbool.h>
#include<string.h>
#include<stdlib.h>
char s[105];
int find(int num)
{
int i;
int flag=1;
int sum=0;
bool visit[100005];
for(i=1;i<=num;i++)
visit[i]=false;
i=1;
while(sum!=num-1)
{
if(i>num)
i=1;
if(visit[i])
{
i++;
continue;
}
else
{
if(flag)
{
flag^=1;
i++;
}
else
{
visit[i++]=true;
flag^=1;
sum++;
}
}
}
for(i=1;i<=num;i++)
if(!visit[i])
return i;
}
int binary(char *str)
{
if(strlen(str)>6)
{
char s[105];
char p1[105];
char p2[105];
int i;
int x,y;
strcpy(s,str);
for(i=0;i<=strlen(str)-1;i++)
{
p1[i]=(str[i]-'0')/2+'0';
if((str[i]-'0')%2!=0&&i!=strlen(str)-1)
str[i+1]+=10;
}
p1[i]='\0';
for(i=strlen(s)-1;i>=0;i--)
{
if(s[i]>=p1[i])
p2[i]=s[i]-p1[i]+'0';
else
{
s[i-1]--;
s[i]+=10;
p2[i]=s[i]-p1[i]+'0';
}
}
p2[strlen(s)]='\0';
x=binary(p1);
y=binary(p2);
return x+y-1;
}
else
return find(atoi(str));
}
int main()
{
gets(s);
printf("%d",binary(s));
return 0;
}
不甘啊