[考试反思]1108csp-s模拟测试105: 傀儡
评测机是真的老了。。。
我的脑力也老了。。。
昨天写完T3之后感觉脑子就留在那了,直到现在还感觉自己神志不清。。。
T1OJ上过了(跑得挺慢但是的确过了),但是文件评测同样是开O2居然只剩下70分。。。
T3全是1.02秒左右的TLE掉了25分。。。
没什么想说的,脑子不在。
for循环用加法实现乘法。大神操作我自己都看不懂。
论玩STL会变成什么样子。int映射为vector再迭代器遍历。
然而那个map除了增加复杂度什么用都没有。。。
T1:小W的魔术
这次还真的没有打表找规律。直接按照定义式子就出来了。
“枚举”左边匹配了i位,为了防止重复,第i+1位不能匹配。然后累加所有合法的串。
1 #include<cstdio> 2 #define mod 998244353 3 #define LL long long 4 LL qpow(LL b,LL t,LL a=1){for(;t;t>>=1,b=b*b%mod)if(t&1)a=a*b%mod;return a;} 5 long long n,ans;int l;char s[1000005]; 6 main(){ 7 freopen("magic.in","r",stdin); 8 freopen("magic.out","w",stdout); 9 scanf("%lld%s",&n,s+1); 10 while(s[l+1])l++; 11 if(n==l)return printf("%lld\n",qpow(26,n)-1),0; 12 for(int i=0;i<l;++i)ans=(ans+25*qpow(26,n-l-1))%mod; 13 printf("%lld\n",(qpow(26,n)-(ans+qpow(26,n-l))+mod+mod)%mod); 14 }
T2:小Y的图
《货车运输》原题。最小生成树+随便一个树上求值。
当然离线下来并查集乱搞也行。因为没有开C++11所以没有unordered_map。复杂度$O(nlog^2n)$了。
把map去掉就对了。
1 #include<bits/stdc++.h> 2 using namespace std; 3 map<int,vector<int> >M[300005]; 4 int f[300005],ans[300005],n,m,q; 5 struct Edge{ 6 int a,b,l; 7 friend bool operator<(Edge a,Edge b){ 8 return a.l<b.l; 9 } 10 }E[300005]; 11 int find(int p){return f[p]==p?p:f[p]=find(f[p]);} 12 void merge(int a,int b,int w){ 13 vector<int>&V=M[a][b]; 14 for(int i=0;i<V.size();++i)ans[V[i]]=w; 15 V=M[b][a]; 16 for(int i=0;i<V.size();++i)ans[V[i]]=w; 17 if(M[a].size()<M[b].size())swap(a,b); 18 for(map<int,vector<int> >::iterator it=M[b].begin();it!=M[b].end();++it){ 19 int x=find((*it).first);V=(*it).second;if(b==x)continue; 20 for(int i=0;i<V.size();++i)if(ans[V[i]]==-1)M[a][x].push_back(V[i]); 21 }f[b]=a; 22 } 23 int main(){ 24 freopen("graph.in","r",stdin); 25 freopen("graph.out","w",stdout); 26 scanf("%d%d%d",&n,&m,&q); 27 for(int i=1;i<=n;++i)f[i]=i; 28 for(int i=1;i<=m;++i)scanf("%d%d%d",&E[i].a,&E[i].b,&E[i].l); 29 for(int i=1,a,b;i<=q;++i)scanf("%d%d",&a,&b),M[a][b].push_back(i),M[b][a].push_back(i),ans[i]=-1*(a!=b); 30 sort(E+1,E+1+m); 31 for(int i=1;i<=m;++i)if(find(E[i].a)!=find(E[i].b))merge(f[E[i].a],f[E[i].b],E[i].l); 32 for(int i=1;i<=q;++i)printf("%d\n",ans[i]); 33 }
T3:小L的数
答案不超过4。01,02,04,08可以构成所有数。
喜欢的数只有45种:01,02...09,12,13,...19,23,24,...,29,34,35,...,39,45,46,...,49,56,57,58,59,67,68,69,78,79,89。
check答案是否为1,2,3,如果都不是答案就是4。
外层枚举喜欢的数,一共有$C_{45}^3$种。内层check(答案为123的做法是一样的,以3为例)
数位dp。(记忆化搜索)。dp[i][j][k]表示到了第i位,这一位的前导0状态为j($2^3$状压状态),当前位需要进位k($0 \leq k \leq 2$)
转移就是枚举每一个喜欢的数的选用情况($3^3$,因为要注意到前导0)
转移比较简单粗暴,按照含义来一直写就行了。
觉得循环展开是没有脸的行为,所以就被卡常了。所以卡了卡加了许多个break也就卡过了。
代码2k其实也能下来。
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define ri register int 4 long long pw[19];int f[19];bool al[19][8][3]; 5 bool dfs(ri ws,ri st,ri up,ri A,ri B,ri C,ri D,ri E,ri F){ 6 if(ws==18)memset(al,0,sizeof al); 7 if(ws==-1&&up==0)return 1; 8 if(ws==-1&&up)return 0; 9 if(al[ws][st][up])return 0; 10 ri g=(up<<3)+(up<<1)+f[ws],nst=0; 11 for(ri i=0;i<3;++i){ 12 if((st&1)&&i==2)break; 13 if(A==0&&i==2)break; 14 ri x=i?B:A;if(i==2)x=0,nst^=nst&1;else nst|=1; 15 if(x>g||x+20<g)continue; 16 for(ri j=0;j<3;++j){ 17 if((st&2)&&j==2)break; 18 if(C==0&&j==2)break; 19 if(!C&&!D&&j)break; 20 ri y=j?D:C;if(j==2)y=0,nst^=nst&2;else nst|=2; 21 if(x+y>g||x+y+11<g)continue; 22 for(ri k=0;k<3;++k){ 23 if((st&4)&&k==2)break; 24 if(E==0&&k==2)break; 25 ri z=k?F:E;if(k==2)z=0; 26 z+=x+y; 27 if(z>g||z+2<g)continue; 28 nst|=st; 29 if(k!=2)nst|=4; 30 if(z==g){if(dfs(ws-1,nst,0,A,B,C,D,E,F))return 1;} 31 else if(z==g-1){if(dfs(ws-1,nst,1,A,B,C,D,E,F))return 1;} 32 else if(dfs(ws-1,nst,2,A,B,C,D,E,F))return 1; 33 } 34 } 35 } 36 al[ws][st][up]=1;return 0; 37 } 38 bool chk1(){ 39 for(ri i=0;i<=9;++i)for(ri j=i+1;j<=9;++j)if(dfs(18,0,0,i,j,0,0,0,0))return 1; 40 return 0; 41 } 42 bool chk2(){ 43 for(ri i=0;i<=9;++i)for(ri j=i+1;j<=9;++j) 44 for(ri k=i;k<=9;++k)for(ri l=max(k+1,i==k?j+1:0);l<=9;++l) 45 if(dfs(18,0,0,i,j,k,l,0,0))return 1; 46 return 0; 47 } 48 bool chk3(){ 49 for(ri i=0;i<=9;++i)for(ri j=i+1;j<=9;++j) 50 for(ri k=i+1;k<=9;++k)for(ri l=max(k+1,i==k?j+1:0);l<=9;++l) 51 for(ri m=k+1;m<=9;++m)for(ri n=max(m+1,k==m?l+1:0);n<=9;++n) 52 if(dfs(18,0,0,i,j,k,l,m,n))return 1; 53 return 0; 54 } 55 int main(){ 56 freopen("number.in","r",stdin); 57 freopen("number.out","w",stdout); 58 ri t;scanf("%d",&t); 59 pw[0]=1;for(ri i=1;i<18;++i)pw[i]=pw[i-1]*10; 60 for(int i=1;i<=t;++i){ 61 long long x;scanf("%lld",&x); 62 for(ri i=0;i<18;++i)f[i]=x/pw[i]%10; 63 if(chk1())puts("1"); 64 else if(chk2())puts("2"); 65 else if(chk3())puts("3"); 66 else puts("4"); 67 } 68 }