• NOIp2018集训test-9-5(pm)


    老张说:这套题太简单啦,你们最多两个小时就可以AK啦!

    题 1 数数

    我看到T1就懵了,这就是老张两个小时可以AK的题的T1??

    然后我成功地T1写了1h+,后面1h打了t2.t3暴力,就很开心。

    等差数列中的一个数B+A*N,发现A非常小,让人浮想联翩,把这个等差数列中每个数模A,得到的结果就是B%A而且很小,就可以数位dp。f[i][j][0/1]表示长度为i的二进制数,模A等于j,前i位有没有达到上界的方案数,g[i][j][0/1]表示这种情况下的答案。转移什么的看代码吧,就是基础的数位dp。

     1 //Achen
     2 #include<algorithm>
     3 #include<iostream>
     4 #include<cstring>
     5 #include<cstdlib>
     6 #include<vector>
     7 #include<cstdio>
     8 #include<queue>
     9 #include<cmath>
    10 #include<set>
    11 #include<map>
    12 #define Formylove return 0
    13 #define For(i,a,b) for(int i=(a);i<=(b);i++)
    14 #define Rep(i,a,b) for(int i=(a);i>=(b);i--)
    15 typedef long long LL;
    16 typedef double db;
    17 using namespace std;
    18 int T,A,lim[65],n;
    19 LL B,N,f[65][10007][2],g[65][10007][2],pr[65],ans; 
    20 
    21 template<typename T>void read(T &x)  {
    22     char ch=getchar(); x=0; T f=1;
    23     while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
    24     if(ch=='-') f=-1,ch=getchar();
    25     for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; x*=f;
    26 }
    27 
    28 LL find(LL up) {
    29     if(!up) return 0;
    30     memset(f,0,sizeof(f));
    31     memset(g,0,sizeof(g));
    32     Rep(i,59,0) if(up&(1LL<<i)) { n=i; break; }
    33     For(i,0,n) lim[n-i]=(up&pr[i])?1:0;
    34     f[0][0][1]=1;
    35     For(i,0,n) {
    36         For(j,0,A-1) if(f[i][j][0]||f[i][j][1]) {
    37             f[i+1][(j*2+1)%A][0]+=f[i][j][0];
    38             g[i+1][(j*2+1)%A][0]+=g[i][j][0]+f[i][j][0];
    39             f[i+1][j*2%A][0]+=f[i][j][0];
    40             g[i+1][j*2%A][0]+=g[i][j][0];
    41             if(lim[i]==0) {
    42                 f[i+1][j*2%A][1]+=f[i][j][1];
    43                 g[i+1][j*2%A][1]+=g[i][j][1];
    44             }
    45             else {
    46                 f[i+1][j*2%A][0]+=f[i][j][1];
    47                 g[i+1][j*2%A][0]+=g[i][j][1];
    48                 f[i+1][(j*2+1)%A][1]+=f[i][j][1];
    49                 g[i+1][(j*2+1)%A][1]+=g[i][j][1]+f[i][j][1];
    50             }
    51         }
    52     }
    53     return g[n+1][B%A][0]+g[n+1][B%A][1]; 
    54 }
    55 
    56 #define ANS
    57 int main() {
    58 #ifdef ANS
    59     freopen("count.in","r",stdin);
    60     freopen("count.out","w",stdout);
    61 #endif
    62     read(T);
    63     pr[0]=1;
    64     For(i,1,60) pr[i]=(pr[i-1]<<1);
    65     while(T--) {
    66         read(A); read(B); read(N);
    67         LL ans=find(B+A*N)-find(max(0LL,B+A-1));
    68         printf("%lld
    ",ans);
    69     }
    70     Formylove;
    71 }
    72 /*
    73 2
    74 10000 5641654165416 100077775545
    75 9980 14244264416 10420477545
    76 */
    View Code

    题 2 旅游

    考试的时候写了个暴力,只有20分,结果发现把题读错了,a,b都为0的点才不能经过,改过后就直接A了??数据大概是用脚造的

    暴力就是把a离散,显然答案就是每种a中选一个点的序列。暴力枚举每种a的每一个点和它的前一种a中的每一个点转移。

    正解我还没看懂,但是二维树状数组那个大概明白了,就是把绝对值拆开,按几种正负分别建树状数组,按a排序后,把a小的一部分加入树状数组,转移都会是一段区间,可以直接查询。

     1 //Achen
     2 #include<algorithm>
     3 #include<iostream>
     4 #include<cstring>
     5 #include<cstdlib>
     6 #include<vector>
     7 #include<cstdio>
     8 #include<queue>
     9 #include<cmath>
    10 #include<set>
    11 #include<map>
    12 #define Formylove return 0
    13 #define For(i,a,b) for(int i=(a);i<=(b);i++)
    14 #define Rep(i,a,b) for(int i=(a);i>=(b);i--)
    15 const int N=1007;
    16 typedef long long LL;
    17 typedef double db;
    18 using namespace std;
    19 int n,m,a[N][N],b[N][N],ls[N*N],sz;
    20 LL f[N][N],ans; 
    21 
    22 template<typename T>void read(T &x)  {
    23     char ch=getchar(); x=0; T f=1;
    24     while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
    25     if(ch=='-') f=-1,ch=getchar();
    26     for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; x*=f;
    27 }
    28 
    29 struct node {
    30     int x,y;
    31     node(){}
    32     node(int x,int y):x(x),y(y){}
    33 }p[N*N];
    34 vector<node>vc[N*N];
    35 
    36 LL dis(node A,node B) { return abs(A.x-B.x)+abs(A.y-B.y);}
    37 
    38 #define ANS
    39 int main() {
    40 #ifdef ANS
    41     freopen("tour.in","r",stdin);
    42     freopen("tour.out","w",stdout);
    43 #endif
    44     read(n); read(m);
    45     For(i,1,n) For(j,1,m) read(a[i][j]),ls[++ls[0]]=a[i][j];
    46     For(i,1,n) For(j,1,m) read(b[i][j]);
    47     sort(ls+1,ls+ls[0]+1);
    48     sz=unique(ls+1,ls+ls[0]+1)-(ls+1);
    49     For(i,1,n) For(j,1,m) {
    50         if(b[i][j]==0&&a[i][j]==0) continue;
    51         a[i][j]=lower_bound(ls+1,ls+sz+1,a[i][j])-ls;
    52         vc[a[i][j]].push_back(node(i,j));
    53         f[i][j]=b[i][j];
    54         vc[a[i][j]].push_back(node(i,j));
    55     }
    56     For(i,2,sz) {
    57         int up1=vc[i].size(),up2=vc[i-1].size();
    58         For(j,0,up1-1) For(k,0,up2-1) {
    59             node t1=vc[i][j],t2=vc[i-1][k];
    60             f[t1.x][t1.y]=max(f[t1.x][t1.y],f[t2.x][t2.y]+dis(t1,t2)+b[t1.x][t1.y]);
    61             ans=max(ans,f[t1.x][t1.y]);
    62         }
    63     } 
    64     printf("%lld
    ",ans);
    65     Formylove;
    66 }
    View Code

    题 3 做梦

    注意读题,每次散步总时间不能超过m,就是每次离开起点到回到起点的时间间隔不超过m。

    最后只有半个小时有点方,然后脑子就很乱,都知道是dp然后矩阵优化就是没搞对,dp还瞎弄了个两维的,只得了暴力分。

    预处理每一次散步的方案,定义f[i][j][k]表示从i点走k步走到j点的方案数(点从1到m),可以用floyd求出。

    然后每次散步走了x步,方案数就是f[1][1][x-2]*2(第一步从0走到1或-1,再不经过0地走x-2步走回1或-1,最后一步走回0)

    g[i]表示散步总步数为i的方案数,也就是n==i的答案。

    $g[n]=sum_{i=2}^{m} g[n-i]*2*f[1][1][i-2]$

    这是个线性递推,矩阵加速即可。

     1 //Achen
     2 #include<algorithm>
     3 #include<iostream>
     4 #include<cstring>
     5 #include<cstdlib>
     6 #include<vector>
     7 #include<cstdio>
     8 #include<queue>
     9 #include<cmath>
    10 #include<set>
    11 #include<map>
    12 #define Formylove return 0
    13 #define For(i,a,b) for(int i=(a);i<=(b);i++)
    14 #define Rep(i,a,b) for(int i=(a);i>=(b);i--)
    15 const int N=107,p=1000000007;
    16 typedef long long LL;
    17 typedef double db;
    18 using namespace std;
    19 int n,m;
    20 LL f[N][N][N],g[N],ans;
    21 
    22 template<typename T>void read(T &x)  {
    23     char ch=getchar(); x=0; T f=1;
    24     while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
    25     if(ch=='-') f=-1,ch=getchar();
    26     for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; x*=f;
    27 }
    28 
    29 struct jz {
    30     LL a[N][N];
    31     friend jz operator *(const jz&A,const jz&B) {
    32         jz rs;
    33         For(i,1,m) For(j,1,m) {
    34             rs.a[i][j]=0;
    35             For(k,1,m) 
    36                 (rs.a[i][j]+=A.a[i][k]*B.a[k][j]%p)%=p;
    37         }
    38         return rs;
    39     }
    40 }bs,rs;
    41 
    42 void ksm(int b) {
    43     while(b) {
    44         if(b&1) rs=rs*bs;
    45         bs=bs*bs;
    46         b>>=1; 
    47     }
    48 }
    49 
    50 #define ANS
    51 int main() {
    52 #ifdef ANS
    53     freopen("dream.in","r",stdin);
    54     freopen("dream.out","w",stdout);
    55 #endif
    56     read(n); read(m);
    57     For(i,1,m) f[i][i-1][1]=1,f[i][i+1][1]=1,f[i][i][0]=1;
    58     For(k,1,m) For(i,1,m) For(j,1,m) {
    59         if(j-1>=1) f[i][j][k]=f[i][j-1][k-1];
    60         if(j+1<=2*m+1) (f[i][j][k]+=f[i][j+1][k-1])%=p;
    61     }
    62     g[0]=1;
    63     For(s,2,m) For(j,2,m) if(s>=j)  
    64         g[s]=(g[s]+g[s-j]*2LL*f[1][1][j-2]%p)%p;
    65     For(i,1,m) For(j,1,m) {
    66         if(i==j) rs.a[i][j]=1;
    67         else rs.a[i][j]=0;
    68         bs.a[i][j]=0;
    69     }
    70     For(i,2,m) bs.a[m-i+1][m]=2*f[1][1][i-2];
    71     For(i,1,m-1) bs.a[i+1][i]=1;
    72     ksm(n-1);
    73     For(i,1,m) 
    74         ans=(ans+rs.a[i][1]*g[i]%p)%p;
    75     printf("%lld
    ",ans);
    76     Formylove;
    77 }
    View Code
  • 相关阅读:
    经典布局 ---- 双飞翼
    细嚼浏览器兼容----条件注释判断浏览器版本
    webqq的注册登记和聊天页面--运用jsonp跨域
    Bootstrap框架的要点--栅格系统
    html5橡皮檫特效
    PHP正确获取客户端IP地址
    常用排序算法及Java实现
    Math类中的floor、ceil和round方法
    Java中的动态反射机制和动态代理
    测试
  • 原文地址:https://www.cnblogs.com/Achenchen/p/9594950.html
Copyright © 2020-2023  润新知