时间限制: 1 Sec 内存限制: 128 MB
【题目描述】
有一个数列 a n a_n an , a 1 a_1 a1 = 1, a i a_i ai + 1 = ( A × a i a_i ai + a i a_i ai mod B ) mod C,要求这个数列第一次出现重复的项的标号。
【输入】
一行三个数,分别表示 A , B , C。
【输出】
输出第一次出现重复项的位置,如果答案超过 2×10^6 输出 −1。
【输入样例】
2 2 9
【输出样例】
4
【提示】
30% 的数据 A , B , C ≤ 10^5;
100% 的数据 A , B , C ≤ 10^9。
【分析】
42分
思路
纯暴力
代码
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#define ll long long int
using namespace std;
ll A,B,C,a[100000005],f[100000005];//注意数组大小,只能开1e8+5。
signed main(){
scanf("%lld%lld%lld",&A,&B,&C);
a[0]=1;
for(ll i=1;i<=100000005;i++){
a[i]=(A*a[i-1]+a[i-1]%B)%C;
f[a[i]]++;
if(f[a[i]]==2){
if(a[i]>2000000){
printf("%lld",-1);
return 0;
}else{
printf("%lld",i);
return 0;
}
}
}
return 0;
}
77分
思路&代码
#include<bits/stdc++.h>
#define ll long long int
using namespace std;
unordered_set<int>node;//定义无序关联式容器
ll A,B,C,a=1;
int main(){
cin>>A>>B>>C;
node.insert(1);
for(int i=1;i<=2000000;i++){
ll b=(A*a+a%B)%C;
if(node.count(b)==1){//count可统计数量
cout<<i;
return 0;
}
node.insert(b);//insert即插入
a=b;
}
cout<<"-1";
return 0;
}
100分
思路
用 h a s h hash hash 来做,用邻接表来存储。就是将每一项的值模一个数,获得一个值作为一个数组的下标,如果这个出现过,用邻接表去存,这样找的时候相当于遍历一个节点的邻接表。
代码
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=2000005,mod=2000005;
int hashh[maxn];
struct z{
int next,v;
}z[maxn];
bool count(int tmp, int tmpp){
for(int i=hashh[tmpp];i;i=z[i].next)if(tmp==z[i].v)return 1;
return 0;
}
int main(){
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
hashh[1]=z[1].v=1;
int tmp=1;
for(int i=1;i<=2000000;i++){
tmp=((ll)a*tmp+tmp%b)%c;
int tmpp=tmp%mod;
if(count(tmp,tmpp)){
printf("%d\n",i);
return 0;
}
z[i+1].v=tmp;
z[i+1].next=hashh[tmpp];
hashh[tmpp]=i+1;
}
puts("-1");
return 0;
}