传送门:Problem H

 https://www.cnblogs.com/violet-acmer/p/9664805.html

题意:

BaoBao在一条有刻度的路上行走(哈哈,搞笑),范围为

[0,n],且都是整数,在当前刻度i的前0.5米处(i+0.5)有红绿灯s[i+1],s[i+1]='0'代表红灯,s[i+1]='1'代表绿灯,遇到红灯需要等一秒变成绿灯后才可以来到i+1处。

每隔一秒所有的灯都会变色。

且没来到一个新的起点p,所有的灯都会恢复初始状态。

 

题解:

打表找规律:
对于样例3
t[0,1]=1
t[0,2]=3,t[1,2]=1
t[0,3]=4,t[1,3]=2,t[2,3]=2
t[0,4]=5,t[1,4]=3,t[2,4]=3,t[3,4]=1
t[0,5]=6,t[1,5]=4,t[2,5]=4,t[3,5]=2,t[4,5]=2
设dp[i]代表来到i处的总时间
例如
dp[1]=t[0,1]=1;
dp[2]=t[0,2]+t[1,2]=4;
dp[3]=t[0,3]+t[1,3]+t[2,3]=8;
dp[4]=t[0,4]+t[1,4]+t[2,4]+t[3,4]=12;
dp[5]=t[0,5]+t[1,5]+t[2,5]+t[3,5]+t[4,5]=18;

在计算dp[3]的时候
dp[3]所包含的所有时间为
t[2,3]
t[0,2]+t[2,3]
t[1,2]+t[2,3]
第一个t[2,3]容易计算,就是判断s[2]是红灯还是绿灯,红灯为2,绿灯为1;
t[0,2]+t[1,2]也容易计算,就是dp[2];


下面来求解后两个t[2,3]的计算:
设change[i,j]表示从i处到j处红绿灯变化的总次数;
计算第一个t[2,3]需要知道change[0,2],如果change[0,2]是奇数,则计算t[2,3]时原先的s[i]的红绿灯状态不变,反之,改变状态;
计算第二个t[2,3]亦是如此,需要知道change[1,2];


难点就在于change[0,2]与change[1,2];
计算容易发现change[0,2]=3,change[1,2]=1;
且通过计算其他的change[i,m](i<m)可以发现,change[0,m]与change[1,m],...,change[m-1,m]同奇偶,而change[m-1,m]与t[m-1,m]同奇偶
此时易得后两个t[2,3]的值是一样的,都和change[1,2]的奇偶以及s[2]状态有关。


故后两个t[2,3]的和x为
if(change[1,2]为奇) x=2*(s[i] == 1 ? 2:1);
else x=2*(s[i] == 1 ? 1:2);
合并为一句话就是
x=2*(s[2] == s[1] ? 1:2);


所以dp[i]=dp[i-1]+(i-1)*(s[i-1] == s[i-2] ? 2:1)+(s[i-1] == '1' ? 1:2);
最终结果是吧所有的dp[i]加起来(0<=i<=n)

 

AC代码:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<string>
 4 #include<cstring>
 5 #define exp 1e-8
 6 #define mian main
 7 #define pii pair<int,int>
 8 #define pll pair<ll,ll>
 9 #define ll long long
10 #define pb push_back
11 #define PI  acos(-1.0)
12 #define inf 0x3f3f3f3f
13 #define w(x) while(x--)
14 #define int_max 2147483647
15 #define lowbit(x) (x)&(-x)
16 #define gcd(a,b) __gcd(a,b)
17 #define pq(x)  priority_queue<x>
18 #define ull unsigned long long
19 #define scn(x) scanf("%d",&x)
20 #define scl(x) scanf("%lld",&x)
21 #define pl(a,n) next_permutation(a,a+n)
22 #define ios ios::sync_with_stdio(false)
23 #define met(a,x) memset((a),(x),sizeof((a)))
24 using namespace std;
25 const int maxn=1e5+10;
26 
27 ll dp[maxn];
28 
29 int main ()
30 {
31     int t;
32     scn(t);
33     string s;
34     while(t--)
35     {
36         cin>>s;
37         int len=s.length();
38         met(dp,0);
39         dp[1]=(s[0] == '0' ? 2:1);
40         for(int i=1;i<len;i++)
41             dp[i+1]=dp[i]+i*((s[i]==s[i-1])?2:1)+((s[i] == '1') ? 1:2);
42 
43         ll ans=0;
44         for(int i=1;i<=len;i++)
45             ans += dp[i];
46         printf("%lld\n",ans);
47     }
48     return 0;
49 }
View Code

相关文章:

  • 2021-10-28
  • 2022-12-23
  • 2021-08-18
  • 2022-12-23
  • 2022-02-17
  • 2021-10-10
猜你喜欢
  • 2021-09-09
  • 2021-11-30
  • 2021-11-05
  • 2021-08-30
  • 2022-01-29
  • 2022-12-23
  • 2022-01-23
相关资源
相似解决方案