HESE20210602GY模拟赛

Posted RymCold

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HESE20210602GY模拟赛相关的知识,希望对你有一定的参考价值。

20210602 模拟赛

T1


极似原题,就是简单的区间DP

观察题目,我们发现它是一个环形结构,但是我们不用怕,咱们怎么办,咱们只需要复制一遍就完了。 然后就是标准的区间DP;

这是一道没有营养的题 ----AWR2020

设一个f[i][j]表示合并到第i和j之间的情况

 for(register int len=2;len<=n;len++)
     for(register int l=1;l<=n-len+1;l++){
     LL r=l+len-1;
     for(register int k=l;k<=r;k++)
     //这是你的操作  
    }

后记:看到数据范围只到了100,想起一个很啥b的做法; 就是每输入一个符号先处理出所有方案,我们只需要多一个O(100!)就可以轻松得到解。 无非就是O(9.3326215443944152681699238856267e+157) 不过就是2.5923948734428931300472010793407e+146个小时就完事了然后就可以得解辣 直接找max就完事了 建议大家都用这个方法。又省时又省力 最主要是不费脑子。

为了整齐一点还是贴一下dei吗罢

 #include<cstdio>
 #include<iostream>
 using namespace std;
 typedef long long LL;
 #define INF 32768
 #define N 120
 inline LL read(){
 LL x=0,y=1;
 char c=getchar();
 while(c<\'0\'||c>\'9\'){if(c==\'-\')y=-y;c=getchar();}
 while(c>=\'0\'&&c<=\'9\'){x=x*10+c-\'0\';c=getchar();}
 return x*y;
 }
 char c[N];
 LL num[N],f[N][N],g[N][N];
 LL n,res=-INF;
 int main (){
 n=read();
 for(register int i=1;i<=n;i++){
 cin>>c[i];
 num[i]=read();
 c[i+n]=c[i];
 num[i+n]=num[i];
 }
 for(register int len=1;len<=n;len++)
   for(register int l=1;l+len-1<=n*2;l++){
  LL r=l+len-1;
  if(len==1) f[l][r]=g[l][r]=num[l];
 else{
 f[l][r]=-INF,g[l][r]=INF;
  for(register int k=l;k<r;k++){
  char op=c[1+k];
  LL minl=g[l][k],minr=g[k+1][r],maxl=f[l][k],maxr=f[k+1][r];
  if(op==\'t\'){
  f[l][r]=max(f[l][r],maxl+maxr);
  g[l][r]=min(g[l][r],minl+minr);
  }
  else{
  LL x1=minl*maxr,x2=minl*minr,x3=maxl*minr,x4=maxl*maxr;
  f[l][r]=max(f[l][r],max(max(x1,x2),max(x3,x4)));
  g[l][r]=min(g[l][r],min(min(x1,x2),min(x3,x4)));
  }
  }
  }
  }
   for(register int i=1;i<=n;i++) res=max(res,f[i][n+i-1]);
   printf("%lld",res);
   return 0;
 }

//yxcyyds!

T2


简单的树形DP

草没看到原题居然只取了和

对于k=1 相信大家都会写没有上司的舞会 对于k=2 相信大家都会写一个简单的转移方程表示一下

k的话,k∈[1,2],且可能影响到父节点 乍一看这个和k=1区别还是蛮大的 qwq不会写了而实际上这个k=2的情况和原题居然只差了下面注掉的一小部分

 #include<cstdio>
 #include<cstring>
 #include<algorithm>
 using namespace std;
 typedef long long LL;
 #define INF 0
 #define N 300010
 inline LL read(){
 LL x=0,y=1;
 char c=getchar();
 while(c<\'0\'||c>\'9\'){if(c==\'-\')y=-y;c=getchar();}
 while(c>=\'0\'&&c<=\'9\'){x=x*10+c-\'0\';c=getchar();}
 return x*y;
 }
 LL n,k,x,y,tot,ans;
 LL f[N][2];
 LL num[N],head[N],edge[N],nxt[N];
 inline void add(LL x,LL y){
 edge[++tot]=y;
 nxt[tot]=head[x];
 head[x]=tot;
 }
 inline void dp1(LL x,LL y){
 f[x][1]++;
 for(register int i=head[x];i;i=nxt[i]){
 LL z=edge[i];
 if(z==y) continue;
 dp1(z,x);
 f[x][0]+=max(f[z][1],f[z][0]);
 f[x][1]+=f[z][0];
 }
 }
 inline void solve1(){
 dp1(1,-1);
 ans=max(f[1][0],f[1][1]);
 }
 inline void dp2(LL x,LL y){
 f[x][1]++;
 LL addup=INF;
 for(register int i=head[x];i;i=nxt[i]){
 LL z=edge[i];
 if(y==z) continue;
 dp2(z,x);
 f[y][1]+=f[z][0];//
 f[x][0]+=f[z][0];
 addup=max(addup,f[z][1]-f[z][0]);//
 }
 f[x][0]+=addup;//
 }
 inline void solve2(){
 dp2(1,0);//
 ans=max(f[1][0],f[1][1]);
 }
 int main(){
 n=read(),k=read();
 for(register int i=1;i<n;i++){
 x=read(),y=read();
 add(x,y);
 }
 if(k==1) solve1();//就是带板子
 else solve2();//可以到上面看一下
 printf("%lld",ans);
 return 0;
 }

另外该题还给出了k<=n的ExT 从同机房大哥那里得到的一个贪心想法:

每次取节点最深的一个点 用单调队列怼进去 一个一个取就行了

不过可惜的是并没有一个很好的证明。尽管大家觉得都没啥问题

T3


18:50 这不就一数位DP吗

Upd 5 hours later 最后机房dalao掘出了暴力过的方法并A掉了 如果说只是基本的数位DP的话这题未免有些枯燥 你套个板子就做完了

然后在网上无意间找到一个奇怪的东西

这是一个神奇的函数——itoa 用处事把一个数改成字符串 我菜的扣脚的数位DP有救了

具体语法(来自C++Reference)

 char *  itoa ( int value, char * str, int base );

//value事被转换的整数 *str处是转换后存在的array base是一个要转换成的2-36的进制数

然后提前处理一下,用另外一个神器strstr查一下就做完了

但是一个缺点事itoa这个函数因为并不是一个标准函数,可能不被某些编译器承认

Upd:就像这样 
PS:博客里懒得搞图床了 脑补一下 [CE in s2oj.jpg]

参考程序:

 #include<cstdio>
 #include<cstring>
 #include<cstdlib>
 using namespace std;
 typedef long long LL;
 #define N 1000010
 inline LL read(){
 LL x=0,y=1;
 char c=getchar();
 while(c<\'0\'||c>\'9\'){if(c==\'-\')y=-y;c=getchar();}
 while(c>=\'0\'&&c<=\'9\'){x=x*10+c-\'0\';c=getchar();}
 return x*y;
 }
 LL a[N],n,m,sum,ans;
 char num[N];
 int main(){
     memset(a,0,sizeof(0));
     for(register int i=1;i<=1000001;i++){
         itoa(i,num,10);
         if(strstr(num,"4")!=NULL){
       a[i]+=a[i-1]+1; //前缀和
   continue;
    }
         if(strstr(num,"62")!=NULL){
       a[i]+=a[i-1]+1;
   continue;
    }
         a[i]=a[i-1];
    }
     while(1){
         n=read(),m=read();
         if(n==0&&m==0) break;
         sum=m-n+1;
 ans=sum-(a[m]-a[n-1]);
         printf("%d\\n",ans);
    }
     return 0;
 }

//这是原题那找到的方法 原题是1000000 可是模拟赛里这道题是10000000 预处理也会爆炸 wkgg为了不让我们用奇技淫巧真是煞费苦心/kk 所以还是乖乖数位DP罢(绝望

好 这是数位DP的方法:

 #include<cstdio>
 #include<cstring>
 #include<algorithm>
 using namespace std;
 typedef long long LL;
 #define N 12
 inline LL read(){
 LL x=0,y=1;
 char c=getchar();
 while(c<\'0\'||c>\'9\'){if(c==\'-\')y=-y;c=getchar();}
 while(c>=\'0\'&&c<=\'9\'){x=x*10+c-\'0\';c=getchar();}
 return x*y;
 }
 bool flag;
 LL num[N],f[N][N];
 LL l,r,tot,ans;
 inline void cl(){
 memset(f,0,sizeof f);
 f[0][0]=1;
 for(register int i=1;i<=8;i++){
 f[i][0]=f[i-1][0]*9-f[i-1][1];
 f[i][1]=f[i-1][0];
 f[i][2]=f[i-1][2]*10+f[i-1][1]+f[i-1][0];
 }
 }
 inline void pre(){
 tot=0,ans=0,flag=0;
 memset(num,0,sizeof num);
 }
 inline LL solve(LL a){
 pre();
 LL ANS=a;
 while(a){
 num[++tot]=a%10;
 a/=10;
 }
 num[tot+1]=0;
 for(register int i=tot;i>0;i--){
 ans+=num[i]*f[i-1][2];
 if(flag)  ans+=num[i]*f[i-1][0];
 else{
 if(num[i]>4) ans+=f[i-1][0];
 if(num[i]>6) ans+=f[i-1][1];
 if(num[i+1]==6&&num[i]>2) ans+=f[i][1];
    }
     if(num[i]==4||(num[i+1]==6&&num[i]==2))  flag=1;
 }
 return ANS-ans;
 }
 int main(){
 cl();
 while(1){
     l=read(),r=read();
 if(l==0&&r==0) break;
 printf("%lld\\n",solve(r+1)-solve(l));
 }
 return 0;
 }

很晕 可能多做几次就好了罢/kk

以上是关于HESE20210602GY模拟赛的主要内容,如果未能解决你的问题,请参考以下文章

STM32模拟IIC与IIC四种实现数字光强采集模块GY30(标准库与HAL库)

20210602 TensorFlow 实现多点线性回归问题

求大神看看Arduino代码 是关于GY-30光照强度传感器的代码

解决“错误 D8016 “/ZI”和“/Gy-”命令行选项不兼容 ”问题

基于STM32的MLX90614(GY-906)人体红外测温

stm32单片机使用串口通信连接GY-33颜色传感器完成对颜色的识别并且打印出其颜色和对应的RGB值