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; } }