启智树提高组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 ,含义如题目描述中所述。

输出

输出一个整数,表示Aloisia需要跳的次数,对1000000007取模。

样例输入

Copy  

样例输入1
2
1 2

样例输入2
4
1 1 2 3

样例输入3
5
1 1 1 1 1
 

样例输出

Copy  

样例输出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ㄒ)/~~

这种小题目要快速思考,给后面的题目留时间。

posted @ 2020-08-18 17:43  Vanilla_chan  阅读(560)  评论(0编辑  收藏  举报