启智树提高组day1T1 3436 : A:Doughnut
启智树提高组day1T1 3436 : A:Doughnut
题目描述
Aloisia有很多很多甜甜圈。有一天,她在地上画了n+1个格子,想从第1个格子跳到第n+1个格子。规则是,Aloisia每到一个格子,都会放一个甜甜圈在里面。在第i个格子时,如果当前甜甜圈的数量是偶数,那么她会跳到第i+1个格子;否则她会跳到第Pi个格子(1≤Pi≤i)。若她到达了第n+1个格子,则立即结束。Aloisia想知道,她要跳多少次才能到达终点。答案对1000000007取模。
输入
输入的第一行包含一个正整数n,表示一共有n+1个格子;
第二行包含n个正整数Pi ,含义如题目描述中所述。
第二行包含n个正整数Pi ,含义如题目描述中所述。
输出
输出一个整数,表示Aloisia需要跳的次数,对1000000007取模。
样例输入
样例输入1 2 1 2 样例输入2 4 1 1 2 3 样例输入3 5 1 1 1 1 1
样例输出
样例输出1 4 样例输出2 20 样例输出3 62
提示
对于20%的数据,有1 ≤ n ≤ 20;
对于40%的数据,有1 ≤ n ≤ 2000;
对于100%的数据,1 ≤ n ≤ 1000000。
要求
时间限制:2.0Sec 内存限制:256MB
建立模型
由样例可得,前进一格后,先放甜甜圈,再判断奇偶性。
故有:对于脚下的格子,如果是奇数次到达则回到p[i],如果是偶数次到达则向后走。
当然,知道这个,也许不能完全做出来。那么就要接下来的性质了。
性质:当第一次走到i+1个格子的时候,前i个格子里面的甜甜圈数量都为偶数个。
又因为,如果是奇数次(比如首次)到底必定回到p[i]后又会前进到i,故这个可以看作是一个递推。
f[i]=f[p[i]~i-1]+2;
f[i]表示第一次走到i格时,要走f[i]步才能走回到第i格
+2意为有两次从i-1走到i
最后,求f[p[i]~i]可以用前缀和(这是我的做法)
亦或,f[i]=f[i-1]+2+(f[i-1]-f[p[i])(std)
数据生成
1 #include<iostream> 2 #include<algorithm> 3 #include<cstdio> 4 #include<cstring> 5 #include<cmath> 6 #include<map> 7 #include<set> 8 #include<queue> 9 #include<vector> 10 #include<ctime> 11 #define IL inline 12 #define re register 13 #define LL long long 14 #define ULL unsigned long long 15 using namespace std; 16 //当到达post时,前面的tt全都是偶数(再走过去就会变成偶数) 17 int n; 18 19 int main() 20 { 21 srand(clock()); 22 cin>>n; 23 freopen("t1.out","w",stdout); 24 cout<<n<<endl; 25 for(int i=1;i<=n;i++) cout<<rand()%i+1<<" "; 26 return 0; 27 }
注意p[i]应当小于等于i。
code
task1
1 #include<iostream> 2 #include<algorithm> 3 #include<cstdio> 4 #include<cstring> 5 #include<cmath> 6 #include<map> 7 #include<set> 8 #include<queue> 9 #include<vector> 10 #define IL inline 11 #define re register 12 #define LL long long 13 #define ULL unsigned long long 14 using namespace std; 15 /* 16 Aloisia每到一个格子,都会放一个甜甜圈在里面。在第i个格子时, 17 18 如果当前甜甜圈的数量是偶数,那么她会跳到第i+1个格子; 19 20 否则她会跳到第Pi个格子(1≤Pi≤i)。 21 22 */ 23 24 IL int read() 25 { 26 int ans=0; 27 bool fu=0; 28 char ch=getchar(); 29 while((ch>'9'||ch<'0')&&ch!='-') ch=getchar(); 30 if(ch=='-') fu=1,ch=getchar(); 31 while(ch<='9'&&ch>='0') ans=(ans<<3)+(ans<<1)+(ch^48),ch=getchar(); 32 if(fu) ans*=-1; 33 return ans; 34 } 35 36 const int M = 1000000007; 37 38 int n,ans; 39 40 int p[1000010]; 41 42 int tt[1000010]; 43 44 int main() 45 { 46 freopen("t1.out","r",stdin); 47 cin>>n; 48 for(int i=1;i<=n;i++) p[i]=read(); 49 int post=1; 50 while(post<=n) 51 { 52 ans++; 53 if(ans>M) ans-=M; 54 55 56 // cout<<ans; 57 // cout<<"当前位置"<<post<<endl; 58 // cout<<"当前tt"<<tt[post]<<endl; 59 60 if(tt[post]&1) tt[post]++,post++; 61 else tt[post]++,post=p[post]; 62 // getchar(); 63 64 } 65 cout<<ans; 66 return 0; 67 }
task2
没打。
task3
1 #include<iostream> 2 #include<algorithm> 3 #include<cstdio> 4 #include<cstring> 5 #include<cmath> 6 #include<map> 7 #include<set> 8 #include<queue> 9 #include<vector> 10 #define IL inline 11 #define re register 12 #define LL long long 13 #define ULL unsigned long long 14 using namespace std; 15 /* 16 Aloisia每到一个格子,都会放一个甜甜圈在里面。在第i个格子时, 17 18 如果当前甜甜圈的数量是偶数,那么她会跳到第i+1个格子; 19 20 否则她会跳到第Pi个格子(1≤Pi≤i)。 21 22 */ 23 24 IL int read() 25 { 26 int ans=0; 27 bool fu=0; 28 char ch=getchar(); 29 while((ch>'9'||ch<'0')&&ch!='-') ch=getchar(); 30 if(ch=='-') fu=1,ch=getchar(); 31 while(ch<='9'&&ch>='0') ans=(ans<<3)+(ans<<1)+(ch^48),ch=getchar(); 32 if(fu) ans*=-1; 33 return ans; 34 } 35 36 const int M = 1000000007; 37 38 int n,ans; 39 40 int p[1000010]; 41 42 bool tt[1000010]; 43 44 int jump[1000010]; 45 46 int qjump[1000010]; 47 48 int main() 49 { 50 freopen("t1.out","r",stdin); 51 cin>>n; 52 for(int i=1;i<=n;i++){ 53 p[i]=read(); 54 jump[i]=2; 55 if(i!=p[i]){ 56 // for(int j=p[i];j<i;j++) jump[i]+=jump[j]; 57 jump[i]+=(qjump[i-1]+M-qjump[p[i]-1])%M; 58 } 59 qjump[i]=qjump[i-1]+jump[i]; 60 qjump[i]%=M; 61 // cout<<i<<" "<<jump[i]<<endl; 62 ans+=jump[i]; 63 ans%=M; 64 } 65 66 cout<<ans; 67 return 0; 68 }
std
1 #include <bits/stdc++.h> 2 3 using namespace std; 4 5 typedef long long ll; 6 7 const int N = 1e6 + 10; 8 9 const int P = 1e9 + 7; 10 11 int n, p[N]; 12 13 ll f[N]; 14 15 16 17 int main(){ 18 19 freopen("Doughnut.in", "r", stdin); 20 21 freopen("Doughnut.out", "w", stdout); 22 23 scanf("%d", &n); 24 25 for(int i = 1;i <= n; i++) 26 27 scanf("%d", &p[i]); 28 29 f[1] = 0; 30 31 for(int i = 1;i <= n; i++) 32 33 f[i + 1] = (f[i] + 1 + f[i] - f[p[i]] + 1) % P; 34 35 printf("%lld\n",(f[n + 1] + P) % P); 36 37 return 0; 38 39 }
小结
考试中得分100。
两天以来唯一一道AC题……(哭/(ㄒoㄒ)/~~
这种小题目要快速思考,给后面的题目留时间。