P05509. 寻找循环节
Description
f[1]=1
f[2]=1
f[3]=(f[2]+f[1])%mod
f[i]=(f[i-1]+f[i-2])%mod;
1<mod<=100000
输出循环节长度
某一个起向右进行到某一个止的一节序列出现,首尾衔接,这一节序列称为循环节
Format
Input
mod的值
Output
循环节长度
Samples
输入数据 1
2
输出数据 1
3
提示 1 1 0 1 1 0 所以循环节是3

#include<iostream>
#include<cstdio>
#include<map>
using namespace std;
map<pair<int,int>,int> w;
int mod,n,x,f[1000001];
int main()
{
scanf("%d",&mod);
f[1]=f[2]=1;
w[make_pair(1,1)]=1;
//将数列的第1项,第2项进行打包,放入map,标为第1块
//后面将会把第2项,第3项进行打包,标为第2块。。。。。。。。。
for(int i=3;;i++)
{
f[i]=(f[i-1]+f[i-2])%mod;
//算出数列第i项
x=w[make_pair(f[i-1],f[i])];
//准备对第(i-1,i)项进行查询,如果能查到的话,则说明前面出现过
//如果没查到,将则 (i-1,i)编号为第i-1块
if(x)
{
printf("%d",i-x-1);
//从前曾被标记为第x块,现在在第i-1块又要出现
//于是循环节长度为i-x-1;
return 0;
}
else
w[make_pair(f[i-1],f[i])]=i-1;
}
}
#include<bits/stdc++.h>
using namespace std;
int mod,f[10000010];
struct node
{
int a,b;
friend bool operator <(node xx,node yy)
{
if(xx.a==yy.a)
return xx.b<yy.b;
else
return xx.a<yy.a;
}//得判全不然map认为两个元素相等
};
map<node,int> mp;
node temp;
int main()
{
cin>>mod;
mp[{1,1}]=1;
f[1]=1,f[2]=1;
for(int i=3;; i++)
{
f[i]=(f[i-1]+f[i-2])%mod;
temp.a=f[i-1];
temp.b=f[i];
if(mp[temp]!=0)
{
cout<<i-mp[temp]-1<<endl;
return 0;
}
mp[temp]=i-1;
}
}
有这样一个递推式
f(1) = 1
f(2) = 1
f(n) = (A * f(n - 1) + B * f(n - 2)) mod 7.
现在给你A,B,n,请求出f(n)的结果来
Format
Input
整个测试包括多组数据,当输入0 0 0代表结束
每个数据一行,给出数字A,B,n
1 <= A, B <= 1000, 1 <= n <= 100,000,000
Output
针对每个数据,一行输出其结果
Samples
输入数据 1
1 1 3
1 2 10
0 0 0
输出数据 1
2
5
SOl
和上一个题差不多,a,b对问题的解决影响不大。
只要某对(f[i-1],f[i-2])从前曾经出现过,则出现循环节。

#include<bits/stdc++.h>
using namespace std;
map<pair<int,int>,int> w;
int mod,a,b,n,x,f[1000001],len;
int vis[111][111];
int main()
{
while (true)
{
scanf("%d%d%d",&a,&b,&n);
if (a == 0 && b == 0 && n == 0)
break;
memset(vis,0,sizeof(vis));
f[1]=f[2]=1;
vis[1][1]=1;
len=0;
for(int i=3;i;i++)
{
f[i]=(a*f[i-1]+b*f[i-2])%7;
//算出数列第i项
if (i==n)
{
cout<<f[i]<<endl;
break;
}
//x=w[make_pair(f[i-1],f[i])];
x=vis[f[i-1]][f[i]];
//准备对第(i-1,i)项进行查询,如果能查到的话,则说明前面出现过
//如果没查到,将则 (i-1,i)编号为第i-1块
if(x)
{
len=i-x-1;
//算出循环节
int temp=x-1;
//算出循环节前面有多少个多余的数字
if (n<=temp)
{
cout<<f[n]<<endl;
break;
}
int nn=(n-temp)%len;
//看落在循环节哪个位置
if (nn==0)
//如果为0的话,则在最后一个位置
nn=len;
printf("%d\n",f[nn+temp]);
// cout<<f[nn+temp]<<endl;
//从前曾被标记为第x块,现在在第i-1块又要出现
//于是循环节长度为i-x-1;
break;
}
else
// w[make_pair(f[i-1],f[i])]=i-1;
vis[f[i-1]][f[i]]=i-1;
}
}
}
#include<iostream>
#include<cstdio>
#include<map>
using namespace std;
map<pair<int,int>,int> w;
int mod,a,b,n,x,f[1000001],len;
int vis[111][111];
int main()
{
//freopen("sequence1.in","r",stdin);
while (true)
{
//cin>>a>>b>>n;
scanf("%d%d%d",&a,&b,&n);
if (a == 0 && b == 0 && n == 0)
break;
w.clear();
f[1]=f[2]=1;
w[make_pair(1,1)]=1;
len=0;
for(int i=3;i;i++)
{
f[i]=(a*f[i-1]+b*f[i-2])%7;
//算出数列第i项
if (i==n)
{
cout<<f[i]<<endl;
break;
}
x=w[make_pair(f[i-1],f[i])];
//准备对第(i-1,i)项进行查询,如果能查到的话,则说明前面出现过
//如果没查到,将则 (i-1,i)编号为第i-1块
if(x)
{
len=i-x-1;
int temp=x-1;
if (n<=temp)
{
cout<<f[n]<<endl;
break;
}
int nn=(n-temp)%len;
if (nn==0)
nn=len;
printf("%d\n",f[nn+temp]);
// cout<<f[nn+temp]<<endl;
//从前曾被标记为第x块,现在在第i-1块又要出现
//于是循环节长度为i-x-1;
break;
}
else
w[make_pair(f[i-1],f[i])]=i-1;
}
}
}
Z2341. 寻找循环节
ID: 4107
传统题
1000ms
256MiB
尝试: 1
已通过: 1
难度: 10
上传者:
管理员 (root)
Description
有这样一个递推式 num[0]=1;
num[1]=2;
num[2]=4;
num[3]=6;
num[i]=(num[i-1]+num[i-3]+num[i-4])%2005;
现希望你求出num[n]来,N<=10^100000000000000000
这种题一看就知道递推式的值存在循环节,问题是循环节的长度是多少呢?
Format
Input
无
Output
输出一个数字,代表循环节
Sol
一个小坑在于,要记四个位置,这样才能确保循环节是对的。
#include<bits/stdc++.h>
using namespace std;
struct node
{
int a,b,c,d;
friend bool operator <(node xx,node yy)
{
// return xx.a==yy.a?xx.b==yy.b?xx.c==yy.c?xx.d<yy.d:xx.c<yy.c:xx.b<yy.b:xx.a<yy.a;
if(xx.a==yy.a)
if(xx.b==yy.b)
if(xx.c==yy.c)
return xx.d<yy.d;
else
return xx.c<yy.c;
else
return xx.b<yy.b;
else
return xx.a<yy.a;
}//得判全不然map认为两个元素相等
};
map<node,int> mp;
int num[11111];
node temp;
int main()
{
num[0]=1;
num[1]=2;
num[2]=4;
num[3]=6;
for (int i=4;i<=11111;i++)
{
num[i]=(num[i-1]+num[i-3]+num[i-4])%2005;
temp.a=num[i-4];
temp.b=num[i-3];
temp.c=num[i-2];
temp.d=num[i-1];
if (mp[temp])
{
cout<<i-mp[temp]<<endl;
break;
}
mp[temp]=i;
}
}

浙公网安备 33010602011771号