• 【XJOI-NOIP16提高模拟训练9】题解。


    http://www.hzxjhs.com:83/contest/55

    说实话这次比赛真的很水。。然而我只拿了140分,面壁反思。

    第一题:

     发现数位和sum最大就是9*18,k最大1000,那么sum*k最大不过2*10^5,若能被x整除,则x也不超过200000,暴力即可。

    不知道学军OIlonglong用%I64d还是%lld输入,用了%I64d爆零。。改成lld就AC了。

     1 #include<cstdio>
     2 #include<cstdlib>
     3 #include<cstring>
     4 #include<iostream>
     5 #include<queue>
     6 using namespace std;
     7 
     8 typedef long long LL;
     9 
    10 int main()
    11 {
    12     freopen("a.in","r",stdin);
    13     freopen("a.out","w",stdout);
    14     int T;
    15     scanf("%d",&T);
    16     while(T--)
    17     {
    18         LL l,r;
    19         int k,ans=0;
    20         scanf("%lld%lld%d",&l,&r,&k);
    21         for(int i=1;i<=200000;i++)
    22         {
    23             if(i>r || i<l) continue;
    24             int sum=0,x=i;
    25             while(x)
    26             {
    27                 sum+=x%10;
    28                 x/=10;
    29             }
    30             if((sum*k%i)==0) ans++;
    31         }
    32         printf("%d
    ",ans);
    33     }
    34     return 0;
    35 }

    第二题

    原本用了矩阵乘法来表示i到j走2^k步有多少种方案,方案数>=1就建一条边,最后跑最短路。。超时,50分。

    然后发现自己真的好傻逼。。

    直接看代码吧。就是一个简单DP,c[i][j][k]表示i到j走2^k步是否可以,d[i][j]表示i到j最少时间。

    if d[i][l][k-1]==1 && d[l][j][k-1]==1   -->  d[i][j][k]=1

     1 #include<cstdio>
     2 #include<cstdlib>
     3 #include<cstring>
     4 #include<iostream>
     5 #include<queue>
     6 using namespace std;
     7 
     8 typedef long long LL;
     9 const int N=60,M=11000;
    10 int n,m,d[N][N];
    11 bool c[N][N][70];
    12 
    13 int minn(int x,int y){return x<y ? x:y;}
    14 
    15 int main()
    16 {
    17     freopen("a.in","r",stdin);
    18     freopen("a.out","w",stdout);
    19     scanf("%d%d",&n,&m);
    20     memset(c,0,sizeof(c));
    21     memset(d,63,sizeof(d));
    22     for(int i=1;i<=m;i++)
    23     {
    24         int x,y;
    25         scanf("%d%d",&x,&y);
    26         d[x][y]=1;
    27         c[x][y][0]=1;
    28     }
    29     for(int k=1;k<=64;k++)
    30         for(int i=1;i<=n;i++)
    31             for(int j=1;j<=n;j++)
    32                 for(int l=1;l<=n;l++)
    33                 {
    34                     if(c[i][l][k-1] && c[l][j][k-1])
    35                     {
    36                         d[i][j]=1;
    37                         c[i][j][k]=1;
    38                     }
    39                 }
    40     for(int i=1;i<=n;i++)
    41         for(int j=1;j<=n;j++)
    42             for(int l=1;l<=n;l++)
    43             {
    44                 d[i][j]=minn(d[i][j],d[i][l]+d[l][j]);
    45             }
    46     printf("%d
    ",d[1][n]);
    47     return 0;
    48 }

    第三题

     直接递归。

    作死用了树状数组维护前缀和,用个数组就好了吧。。

    用树状数组超时90分,改成数组就A了。

     1 #include<cstdio>
     2 #include<cstdlib>
     3 #include<cstring>
     4 #include<iostream>
     5 #include<queue>
     6 using namespace std;
     7 
     8 const int N=1100;
     9 char s[N];
    10 int n,c[N],d[N][N][2];
    11 
    12 int lowbit(int x){return x&(-x);}
    13 void add(int x,int d){
    14     for(int i=x;i<=n;i+=lowbit(i)) c[i]+=d;
    15 }
    16 int getsum(int x){
    17     int ans=0;
    18     for(int i=x;i>=1;i-=lowbit(i)) ans+=c[i];
    19     return ans;
    20 }
    21 
    22 bool check(int l,int r,int tmp)
    23 {
    24     if(d[l][r][tmp]!=-1) return d[l][r][tmp];
    25     if(l>r) return 0;
    26     if((getsum(r)-getsum(l-1))&1) return d[l][r][tmp]=0;    
    27     if(tmp==0)
    28     {
    29         if(l==r && s[l]=='0') return d[l][r][tmp]=1;
    30         if(s[l]=='1' && s[r]=='1' && check(l+1,r-1,1)) return d[l][r][tmp]=1;
    31         return d[l][r][tmp]=0;
    32     }
    33     else
    34     {
    35         int t=getsum(l-1);
    36         for(int i=l;i<r;i++)
    37         {
    38             if((getsum(i)-t)&1) {d[l][i][0]=d[i+1][r][0]=0;continue;}
    39             if(check(l,i,0) && check(i+1,r,0)) return d[l][r][tmp]=1;
    40         }
    41         return d[l][r][tmp]=0;
    42     }
    43 }
    44 
    45 int main()
    46 {
    47     freopen("a.in","r",stdin);
    48     // freopen("a.out","w",stdout);
    49     int T;
    50     scanf("%d",&T);
    51     while(T--)
    52     {
    53         scanf("%d",&n);
    54         scanf("%s",s+1);
    55         memset(c,0,sizeof(c));
    56         memset(d,-1,sizeof(d));
    57         for(int i=1;i<=n;i++)
    58             if(s[i]=='1') add(i,1);
    59         if(check(1,n,0)) printf("YES
    ");
    60         else printf("NO
    ");
    61     }
    62     return 0;
    63 }
  • 相关阅读:
    模型定义
    聚合、原生和子查询
    PHP curl扩展
    时间查询
    查询表达式
    HTTP协议的Keep-Alive 模式
    抽象类可以没有抽象方法
    Nginx解决前端跨域问题,Nginx反向代理跨域原理
    Nginx配置文件不生效,Nginx配置文件重启也不生效
    php openssl加密解密函数
  • 原文地址:https://www.cnblogs.com/KonjakJuruo/p/5685270.html
Copyright © 2020-2023  润新知