2017-2018 ACM-ICPC Latin American Regional Programming Contest J - Jumping frog 題解(gcd)
阿新 • • 發佈:2020-10-27
題目連結
題目大意
一隻青蛙在長度為N的字串上跳躍,“R”可以跳上去,“P”不可以跳上去。
字串是環形的,N-1和0相連。
青蛙的跳躍距離K的取值範圍是[1, N-1],選定K之後不可改變。
要求青蛙最後能跳回起點(起點可以是0-N-1的任意一個位置),問K的取值有多少種選擇。
\(3≤N≤{10}^5\)。
題目思路
主要是要發現每一次走的步數一定是gcd(i,n)
然後發現gcd只有log(n)(可能多一些,但是沒多太大)
然後O(n) check
程式碼
#include<set> #include<map> #include<queue> #include<stack> #include<cmath> #include<cstdio> #include<vector> #include<string> #include<cstring> #include<iostream> #include<algorithm> #include<unordered_map> #define fi first #define se second //#define int long long #define debug printf(" I am here\n"); using namespace std; typedef long long ll; typedef unsigned long long ull; typedef pair<int,int> pii; const ll INF=0x3f3f3f3f3f3f3f3f; const int maxn=1e6+5,inf=0x3f3f3f3f,mod=1e9+7; const double eps=1e-10; char s[maxn]; int n; int vis[maxn]; int gcd(int a,int b){ return b==0?a:gcd(b,a%b); } bool check(int x){ for(int i=1;i<=x;i++){ bool flag=1; for(int j=i;j<=n;j+=x){ if(s[j]=='P'){ flag=0; break; } } if(flag) return 1; } return 0; } signed main(){ memset(vis,-1,sizeof(vis)); scanf("%s",s+1); n=strlen(s+1); int ans=0; for(int i=1;i<=n-1;i++){ int x=gcd(i,n); if(vis[x]==-1){ if(check(x)){ vis[x]=1; }else{ vis[x]=0; } } ans+=vis[x]; } printf("%d\n",ans); return 0; }