今天H题真的有毒,居然不放单组数据范围……SAM卡了半天空间打死过不去
J题卡牛顿迭代常数也是很那啥的
补题进度:10/12
A.
签到题,模拟
1 #include<bits/stdc++.h> 2 using namespace std; 3 int T; 4 int main() 5 { 6 scanf("%d",&T); 7 while(T--) 8 { 9 string s; 10 cin>>s; 11 for(int i=0;i<s.length();++i) 12 { 13 if('A'<=s[i]&&s[i]<='Z')s[i]=s[i]-'A'+'a'; 14 } 15 if(s=="jessie")puts("Good guy!"); 16 else puts("Dare you say that again?"); 17 } 18 return 0; 19 }
B.
dp,维护最大值和最小值,互相转移
注意一下边界条件
1 #include<bits/stdc++.h> 2 #define maxn 2005 3 #define inf 1e17 4 #define ll long long 5 using namespace std; 6 int T,n,m,k; 7 ll a[maxn]; 8 char b[8]; 9 ll f[8][maxn],g[8][maxn]; 10 int main() 11 { 12 scanf("%d",&T); 13 while(T--) 14 { 15 scanf("%d%d%d",&n,&m,&k); 16 for(int i=1;i<=n;++i)scanf("%lld",&a[i]); 17 scanf("%s",b+1); 18 for(int i=0;i<=n;++i)f[0][i]=g[0][i]=k; 19 ll ans=-inf; 20 for(int i=1;i<=m;++i) 21 { 22 for(int j=i;j<=n;++j) 23 { 24 if(b[i]=='+') 25 { 26 f[i][j]=f[i-1][j-1]+a[j]; 27 g[i][j]=g[i-1][j-1]+a[j]; 28 } 29 if(b[i]=='-') 30 { 31 f[i][j]=f[i-1][j-1]-a[j]; 32 g[i][j]=g[i-1][j-1]-a[j]; 33 } 34 if(b[i]=='*') 35 { 36 f[i][j]=max(f[i-1][j-1]*a[j],g[i-1][j-1]*a[j]); 37 g[i][j]=min(f[i-1][j-1]*a[j],g[i-1][j-1]*a[j]); 38 } 39 if(b[i]=='/') 40 { 41 f[i][j]=max(f[i-1][j-1]/a[j],g[i-1][j-1]/a[j]); 42 g[i][j]=min(f[i-1][j-1]/a[j],g[i-1][j-1]/a[j]); 43 } 44 if(j>i) 45 { 46 f[i][j]=max(f[i][j],f[i][j-1]); 47 g[i][j]=min(g[i][j],g[i][j-1]); 48 } 49 } 50 } 51 cout<<f[m][n]<<endl; 52 } 53 return 0; 54 }
G.
打表找规律,发现是2^(n-1),欧拉定理指数取模一下
1 #include<bits/stdc++.h> 2 #define ll long long 3 #define maxn 1000005 4 using namespace std; 5 const ll mod=1000000007; 6 int T; 7 char s[maxn]; 8 ll fastpow(ll a,ll p) 9 { 10 ll ans=1; 11 while(p) 12 { 13 if(p&1)ans=ans*a%mod; 14 a=a*a%mod; 15 p>>=1; 16 } 17 return ans; 18 } 19 int main() 20 { 21 scanf("%d",&T); 22 while(T--) 23 { 24 scanf("%s",s+1); 25 ll n=0,len=strlen(s+1); 26 for(int i=1;i<=len;++i)n=n*10+s[i]-'0',n%=(mod-1); 27 n=(n-1+(mod-1))%(mod-1); 28 ll ans=fastpow(2,n); 29 cout<<ans<<endl; 30 } 31 return 0; 32 }
E.
显然树链剖分,然后加和乘用双标记线段树维护
考虑取模意义下取反操作,bitwise not x=2^64-1-x=-1-x=(-1)*(x+1)=(2^64-1)*x+(2^64-1)
然后就变成了加和乘操作
mod 2^64 用unsigned long long的自然溢出就行了
1 #include<bits/stdc++.h> 2 #define ll unsigned long long 3 #define maxn 100005 4 const ll maxf=(ll)18446744073709551615; 5 using namespace std; 6 int n,q; 7 vector<int> g[maxn]; 8 int d[maxn],fa[maxn],size[maxn],wson[maxn]; 9 void dfs1(int u) 10 { 11 size[u]=1;wson[u]=0; 12 for(int i=0;i<g[u].size();++i) 13 { 14 int v=g[u][i]; 15 d[v]=d[u]+1;fa[v]=u; 16 dfs1(v); 17 size[u]+=size[v]; 18 if(size[v]>size[wson[u]])wson[u]=v; 19 } 20 } 21 int top[maxn],lpos[maxn],cnt; 22 void dfs2(int u,int TOP) 23 { 24 top[u]=TOP; 25 lpos[u]=++cnt; 26 if(wson[u])dfs2(wson[u],TOP); 27 for(int i=0;i<g[u].size();++i) 28 { 29 int v=g[u][i]; 30 if(v==wson[u])continue; 31 dfs2(v,v); 32 } 33 } 34 ll sumv[maxn<<2],addv[maxn<<2],mulv[maxn<<2]; 35 void pushup(int rt) 36 { 37 sumv[rt]=sumv[rt<<1]+sumv[rt<<1|1]; 38 } 39 void pushdown(int rt,int l,int r) 40 { 41 int mid=(l+r)>>1; 42 if(mulv[rt]!=1) 43 { 44 ll t=mulv[rt]; 45 sumv[rt<<1]*=t;sumv[rt<<1|1]*=t; 46 addv[rt<<1]*=t;addv[rt<<1|1]*=t; 47 mulv[rt<<1]*=t;mulv[rt<<1|1]*=t; 48 mulv[rt]=1; 49 } 50 if(addv[rt]) 51 { 52 ll t=addv[rt]; 53 sumv[rt<<1]+=t*(mid-l+1);sumv[rt<<1|1]+=t*(r-mid); 54 addv[rt<<1]+=t;addv[rt<<1|1]+=t; 55 addv[rt]=0; 56 } 57 } 58 void build(int rt,int l,int r) 59 { 60 sumv[rt]=0;addv[rt]=0;mulv[rt]=1; 61 if(l==r) 62 { 63 return; 64 } 65 int mid=(l+r)>>1; 66 build(rt<<1,l,mid);build(rt<<1|1,mid+1,r); 67 pushup(rt); 68 } 69 void add(int rt,int l,int r,int ql,int qr,ll v) 70 { 71 int mid=(l+r)>>1; 72 if(ql<=l&&r<=qr) 73 { 74 sumv[rt]+=v*(r-l+1);addv[rt]+=v; 75 return; 76 } 77 pushdown(rt,l,r); 78 if(ql<=mid)add(rt<<1,l,mid,ql,qr,v); 79 if(qr>mid)add(rt<<1|1,mid+1,r,ql,qr,v); 80 pushup(rt); 81 } 82 void mul(int rt,int l,int r,int ql,int qr,ll v) 83 { 84 int mid=(l+r)>>1; 85 if(ql<=l&&r<=qr) 86 { 87 sumv[rt]*=v;addv[rt]*=v;mulv[rt]*=v; 88 return; 89 } 90 pushdown(rt,l,r); 91 if(ql<=mid)mul(rt<<1,l,mid,ql,qr,v); 92 if(qr>mid)mul(rt<<1|1,mid+1,r,ql,qr,v); 93 pushup(rt); 94 } 95 ll query(int rt,int l,int r,int ql,int qr) 96 { 97 int mid=(l+r)>>1; 98 if(ql<=l&&r<=qr)return sumv[rt]; 99 pushdown(rt,l,r); 100 ll ans=0; 101 if(ql<=mid)ans+=query(rt<<1,l,mid,ql,qr); 102 if(qr>mid)ans+=query(rt<<1|1,mid+1,r,ql,qr); 103 pushup(rt); 104 return ans; 105 } 106 void add(int u,int v,ll w) 107 { 108 while(top[u]!=top[v]) 109 { 110 if(d[top[u]]<d[top[v]])swap(u,v); 111 add(1,1,n,lpos[top[u]],lpos[u],w); 112 u=fa[top[u]]; 113 } 114 if(d[u]<d[v])swap(u,v); 115 add(1,1,n,lpos[v],lpos[u],w); 116 } 117 void mul(int u,int v,ll w) 118 { 119 while(top[u]!=top[v]) 120 { 121 if(d[top[u]]<d[top[v]])swap(u,v); 122 mul(1,1,n,lpos[top[u]],lpos[u],w); 123 u=fa[top[u]]; 124 } 125 if(d[u]<d[v])swap(u,v); 126 mul(1,1,n,lpos[v],lpos[u],w); 127 } 128 ll query(int u,int v) 129 { 130 ll ans=0; 131 while(top[u]!=top[v]) 132 { 133 if(d[top[u]]<d[top[v]])swap(u,v); 134 ans+=query(1,1,n,lpos[top[u]],lpos[u]); 135 u=fa[top[u]]; 136 } 137 if(d[u]<d[v])swap(u,v); 138 ans+=query(1,1,n,lpos[v],lpos[u]); 139 return ans; 140 } 141 int main() 142 { 143 while(~scanf("%d",&n)) 144 { 145 for(int i=1;i<=n;++i)g[i].clear(),fa[i]=0,d[i]=0; 146 cnt=0; 147 for(int i=2;i<=n;++i) 148 { 149 int x;scanf("%d",&x); 150 g[x].push_back(i); 151 } 152 d[1]=1; 153 dfs1(1);dfs2(1,1); 154 build(1,1,n); 155 scanf("%d",&q); 156 while(q--) 157 { 158 int opt,u,v;ll x; 159 scanf("%d%d%d",&opt,&u,&v); 160 if(opt<=2)scanf("%llu",&x); 161 if(opt==1) 162 { 163 mul(u,v,x); 164 } 165 if(opt==2) 166 { 167 add(u,v,x); 168 } 169 if(opt==3) 170 { 171 mul(u,v,maxf); 172 add(u,v,maxf); 173 } 174 if(opt==4) 175 { 176 printf("%llu\n",query(u,v)); 177 } 178 } 179 } 180 return 0; 181 }
F.
裸的区间k覆盖,最大费用流
连边:(i,i+1,k,0),(a[i],b[i]+1,1,-w),(s,1,k,0),(n+1,t,k,0)
(居然卡常数,拆点的费用流被卡掉了,只能(a[i]->b[i]+1)连边)
1 #include<bits/stdc++.h> 2 #define inf 1000000000 3 #define maxn 805 4 using namespace std; 5 int T; 6 int n,m,k; 7 int a[maxn],b[maxn],w[maxn]; 8 int c[maxn]; 9 int head[maxn],p,s,t; 10 struct edge 11 { 12 int from,to,next,f,c; 13 }e[maxn*10]; 14 void addedge(int u,int v,int f,int c) 15 { 16 e[p].from=u;e[p].to=v;e[p].f=f;e[p].c=c;e[p].next=head[u];head[u]=p++; 17 e[p].from=v;e[p].to=u;e[p].f=0;e[p].c=-c;e[p].next=head[v];head[v]=p++; 18 } 19 int dis[maxn],inq[maxn],pre[maxn]; 20 bool vis[maxn]; 21 bool spfa(int s,int t) 22 { 23 memset(inq,0,sizeof(inq)); 24 memset(pre,-1,sizeof(pre)); 25 queue<int> q; 26 for(int i=s;i<=t;i++)dis[i]=inf;dis[s]=0; 27 q.push(s);inq[s]=1; 28 while(!q.empty()) 29 { 30 int u=q.front();q.pop();inq[u]=0; 31 for(int i=head[u];i!=-1;i=e[i].next) 32 { 33 int v=e[i].to,f=e[i].f,c=e[i].c; 34 if(f&&dis[v]>dis[u]+c) 35 { 36 dis[v]=dis[u]+c;pre[v]=i; 37 if(!inq[v])inq[v]=1,q.push(v); 38 } 39 } 40 } 41 return dis[t]!=inf; 42 } 43 int dfs(int u,int maxf,int t) 44 { 45 if(u==t)return maxf;int tmp=0; 46 vis[u]=1; 47 for(int i=head[u];i!=-1&&tmp<maxf;i=e[i].next)if(!vis[e[i].to]) 48 { 49 int v=e[i].to,f=e[i].f,c=e[i].c; 50 if(f&&dis[v]==dis[u]+c) 51 { 52 int minn=min(maxf-tmp,f); 53 f=dfs(v,minn,t);tmp+=f;e[i].f-=f;e[i^1].f+=f; 54 } 55 } 56 return tmp; 57 } 58 int mcmf(int s,int t) 59 { 60 int ans=0; 61 while(spfa(s,t)) 62 { 63 memset(vis,0,sizeof(vis)); 64 ans+=dfs(s,inf,t)*dis[t]; 65 } 66 return ans; 67 } 68 int main() 69 { 70 scanf("%d",&T); 71 while(T--) 72 { 73 scanf("%d%d%d",&n,&k,&m); 74 for(int i=1;i<=m;++i) 75 { 76 scanf("%d%d%d",&a[i],&b[i],&w[i]); 77 c[2*i-1]=a[i];c[2*i]=b[i]; 78 } 79 sort(c+1,c+2*m+1); 80 n=unique(c+1,c+2*m+1)-c-1; 81 p=0; 82 memset(head,-1,sizeof(head)); 83 s=0;t=n+2; 84 for(int i=1;i<=m;++i) 85 { 86 a[i]=lower_bound(c+1,c+n+1,a[i])-c; 87 b[i]=lower_bound(c+1,c+n+1,b[i])-c; 88 } 89 for(int i=1;i<=n;++i)addedge(i,i+1,k,0); 90 for(int i=1;i<=m;++i)addedge(a[i],b[i]+1,1,-w[i]); 91 addedge(s,1,k,0); 92 addedge(n+1,t,k,0); 93 int ans=abs(mcmf(s,t)); 94 printf("%d\n",ans); 95 } 96 return 0; 97 }
H.
后缀自动机裸题,统计right集合大小在[A,B]之间的,每次maxlen[u]-minlen[u]+1就行
1 #include<bits/stdc++.h> 2 #define ll long long 3 #define maxn 200005 4 using namespace std; 5 int ch[maxn][26]; 6 int fa[maxn],cnt,last,rt; 7 ll sz[maxn],dis[maxn]; 8 void init() 9 { 10 cnt=0; 11 rt=last=++cnt; 12 memset(fa,0,sizeof(fa)); 13 memset(dis,0,sizeof(dis)); 14 memset(sz,0,sizeof(sz)); 15 memset(ch,0,sizeof(ch)); 16 } 17 inline int newnode(int x){dis[++cnt]=x;return cnt;} 18 void add(int x) 19 { 20 int np=newnode(dis[last]+1),p=last; 21 for(;p&&(!ch[p][x]);p=fa[p])ch[p][x]=np; 22 if(!p)fa[np]=rt; 23 else 24 { 25 int q=ch[p][x]; 26 if(dis[q]==dis[p]+1)fa[np]=q; 27 else 28 { 29 int nq=newnode(dis[p]+1); 30 memcpy(ch[nq],ch[q],sizeof(ch[q])); 31 fa[nq]=fa[q]; 32 fa[q]=fa[np]=nq; 33 for(;ch[p][x]==q;p=fa[p])ch[p][x]=nq; 34 } 35 } 36 last=np; 37 sz[np]=1; 38 } 39 char s[maxn]; 40 int A,B; 41 int c[maxn],t[maxn]; 42 ll count() 43 { 44 memset(c,0,sizeof(c)); 45 memset(t,0,sizeof(t)); 46 ll ans=0; 47 for(int i=1;i<=cnt;i++)c[dis[i]]++; 48 for(int i=1;i<=cnt;i++)c[i]+=c[i-1]; 49 for(int i=cnt;i;i--)t[c[dis[i]]--]=i; 50 for(int i=cnt;i;i--){int x=t[i];sz[fa[x]]+=sz[x];} 51 for(int i=2;i<=cnt;++i)if(A<=sz[i]&&sz[i]<=B)ans+=dis[i]-dis[fa[i]]; 52 return ans; 53 } 54 int main() 55 { 56 while(~scanf("%s%d%d",s+1,&A,&B)) 57 { 58 init(); 59 for(int i=1;s[i];++i)add(s[i]-'A'); 60 cout<<count()<<endl; 61 } 62 return 0; 63 }
I.
观察一下,三个都是奇数显然不行,否则显然可以
1 #include<bits/stdc++.h> 2 using namespace std; 3 int a,b,c; 4 int main() 5 { 6 while(~scanf("%d%d%d",&a,&b,&c)) 7 { 8 if((a&1)&&(b&1)&&(c&1))puts("No"); 9 else puts("Yes"); 10 } 11 return 0; 12 }
J.
牛顿迭代打死卡不过去,跑1.5s
学习了一波二次剩余的姿势
若x^2=n(mod p),则pow(n,(p-1)/2)=1(mod p)
然后我们选一些大质数判一判就好了
1 #include<bits/stdc++.h> 2 #define maxn 205 3 #define ll long long 4 using namespace std; 5 int T; 6 const ll M[11]={1000000181,1000000007,1000000009,998244353,1000000021,1000000087,1000000223,1000000241,1000000579,1000000531,1000000607}; 7 char str[maxn]; 8 ll fastpow(ll a,ll p,ll mod) 9 { 10 ll ans=1; 11 while(p) 12 { 13 if(p&1)ans=ans*a%mod; 14 a=a*a%mod;p>>=1; 15 } 16 return ans; 17 } 18 int main() 19 { 20 scanf("%d",&T); 21 while(T--) 22 { 23 scanf("%s",str+1); 24 int len=strlen(str+1); 25 if(len==1&&str[1]=='1') 26 { 27 puts("Arena of Valor"); 28 continue; 29 } 30 bool yes1=1,yes2=1; 31 for(int i=0;i<=10;++i) 32 { 33 ll mod=M[i]; 34 ll n=0; 35 for(int j=1;j<=len;++j)n=n*10+str[j]-'0',n%=mod; 36 ll m=(n-1+mod)%mod; 37 ll res=n*m%mod*fastpow(2,mod-2,mod)%mod; 38 ll x=fastpow(res,(mod-1)/2,mod); 39 if(x!=1)yes1=0; 40 ll y=fastpow(n,(mod-1)/2,mod); 41 if(y!=1)yes2=0; 42 } 43 if(yes1&&yes2) 44 { 45 puts("Arena of Valor"); 46 } 47 else if((yes1)&&(!yes2)) 48 { 49 puts("Clash Royale"); 50 } 51 else if((!yes1)&&(yes2)) 52 { 53 puts("Hearth Stone"); 54 } 55 else if((!yes1)&&(!yes2)) 56 { 57 puts("League of Legends"); 58 } 59 } 60 return 0; 61 }
K.
多重背包计数,暴力dp为O(N*S*S)的
考虑把转移中的O(S)优化掉:
如果没有c[i]限制,那么每次记录 mod v[i]意义下分类的总和,每次加上总和即可
现在有了c[i]限制,考虑mod v[i]意义下是连续的一段转移过来的,所以用滑动窗口维护下就行了
1 #include<bits/stdc++.h> 2 #define ll long long 3 #define maxn 22 4 #define maxc 10005 5 using namespace std; 6 const ll mod=1000000007; 7 int T,n,q; 8 ll v[maxn],c[maxn]; 9 ll dp[maxn][maxc],tmp[maxn]; 10 queue<ll> que[maxn]; 11 int main() 12 { 13 scanf("%d",&T); 14 while(T--) 15 { 16 memset(dp,0,sizeof(dp)); 17 scanf("%d%d",&n,&q); 18 for(int i=1;i<=n;++i)scanf("%lld%lld",&v[i],&c[i]); 19 dp[0][0]=1; 20 for(int i=1;i<=n;++i) 21 { 22 memset(tmp,0,sizeof(tmp)); 23 for(int i=0;i<=20;++i)while(!que[i].empty())que[i].pop(); 24 for(int j=0;j<=10000;++j) 25 { 26 tmp[j%v[i]]+=dp[i-1][j]; 27 tmp[j%v[i]]%=mod; 28 if(j>=((1<<c[i]))*v[i])tmp[j%v[i]]-=que[j%v[i]].front(),que[j%v[i]].pop(),tmp[j%v[i]]=(tmp[j%v[i]]%mod+mod)%mod; 29 que[j%v[i]].push(dp[i-1][j]); 30 dp[i][j]+=tmp[j%v[i]];dp[i][j]%=mod; 31 } 32 } 33 while(q--) 34 { 35 int s; 36 scanf("%d",&s); 37 printf("%d\n",(int)dp[n][s]); 38 } 39 } 40 return 0; 41 }
L.
dp;
f(i,j,k)表示现在是第i天,状态为j(0/1/2),上一天状态为k(0/1/2)
f(i,0,0)=f(i-1,0,1)+f(i-1,0,2);
f(i,0,1)=f(i-1,1,0)+f(i-1,1,1)+f(i-1,1,2);
f(i,0,2)=f(i-1,2,0)+f(i-1,2,2);
f(i,1,0)=f(i,0,1);
f(i,1,1)=f(i,0,0);
f(i,1,2)=f(i,0,2);
f(i,2,0)=f(i-1,0,0)+f(i-1,0,1);
f(i,2,1)=f(i,2,0);
f(i,2,2)=f(i-1,2,0)+f(i-1,2,1);
然后发现都是线性齐次递推,直接构造9*9的矩阵,上矩阵快速幂
1 #include<bits/stdc++.h> 2 #define ll long long 3 using namespace std; 4 const ll mod=1000000007; 5 int T; 6 ll n; 7 const int m=9; 8 struct Matrix 9 { 10 ll a[25][25]; 11 void clear(){memset(a,0,sizeof(a));} 12 void init(){memset(a,0,sizeof(a));for(int i=1;i<=m;i++)a[i][i]=1;} 13 }; 14 Matrix operator * (Matrix a,Matrix b) 15 { 16 Matrix c;c.clear(); 17 for(int i=1;i<=m;i++) 18 for(int j=1;j<=m;j++) 19 for(int k=1;k<=m;k++) 20 c.a[i][j]+=a.a[i][k]*b.a[k][j]%mod,c.a[i][j]%=mod; 21 return c; 22 } 23 Matrix fastpow(Matrix a,ll p) 24 { 25 Matrix ans;ans.init(); 26 for(;p;p>>=1,a=a*a)if(p&1)ans=ans*a; 27 return ans; 28 } 29 int main() 30 { 31 cin>>T; 32 while(T--) 33 { 34 cin>>n; 35 if(n==1) 36 { 37 puts("3"); 38 continue; 39 } 40 Matrix A;A.clear(); 41 A.a[1][2]=A.a[1][3]=A.a[2][4]=A.a[2][5]=A.a[2][6]=A.a[3][7]=A.a[3][9]=A.a[4][4]=A.a[4][5]=A.a[4][6]=1; 42 A.a[5][2]=A.a[5][3]=A.a[6][7]=A.a[6][9]=A.a[7][1]=A.a[7][2]=A.a[8][1]=A.a[8][2]=A.a[9][7]=A.a[9][8]=1; 43 Matrix res=fastpow(A,n-2); 44 Matrix tmp;tmp.clear(); 45 for(int i=1;i<=9;++i)tmp.a[i][1]=1; 46 Matrix R=res*tmp; 47 ll ans=0; 48 for(int i=1;i<=9;++i)ans+=R.a[i][1]; 49 ans%=mod; 50 cout<<ans<<endl; 51 } 52 return 0; 53 }