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\n",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\n",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\n",ans);
76     Formylove;
77 }
View Code

猜你喜欢

转载自www.cnblogs.com/Achenchen/p/9594950.html