牛客网暑期ACM多校训练营day4
A 根据题意找出递推式 发现上一项的ans作为下一项的幂次 所以欧拉降幂 (写错递归 背锅背锅
#include<iostream> #include<algorithm> #include<queue> #include<vector> #include<map> #include<set> #include<cstring> #include<cstdio> #define N 3000006 #define ll long long using namespace std; const int MAXN=2e5+7; int cnt; char s[MAXN]; int mul[N]; bool notprime[N]; int prime[N]; ll c1,c2,c3,c4,c5,c6,c0,c7; long long qpow(long long a,long long b,long long c){ long long t=1;long long e=a; while(b!=0){ if((b&1)==1) t=t*e%c; e=e*e%c; b=b>>1; } return t; } void Prime(){ notprime[1]=1; cnt=0; mul[1]=1; for(int i=2;i<N;i++){ if(notprime[i]==0){ prime[++cnt]=i; mul[i]=i-1; } for(int j=1;j<=cnt&&prime[j]*i<N;j++){ if(notprime[i*prime[j]]==0) notprime[i*prime[j]]=1; if(i%prime[j]==0){ mul[i*prime[j]]=mul[i]*prime[j];break; } else{ mul[i*prime[j]]=mul[i]*(prime[j]-1); } } } } ll dfs(int x, ll mod) { if(mod==1||x==0)return 0; if(s[x]=='2') { ll p; if(mod==c0)p=c1; else if(mod==c1)p=c2; else if(mod==c2)p=c3; else if(mod==c3)p=c4; else if(mod==c4)p=c5; else if(mod==c5)p=c6; else if(mod==c6)p=c7; else p=mul[mod]; ll tmp=(qpow(2,(dfs(x-1,p)+p)%p,mod)*6LL%mod-3LL+mod)%mod; return tmp; } if(s[x]=='0') { return (dfs(x-1,mod)+1LL+mod)%mod; } if(s[x] =='1'){ return (2LL*dfs(x-1,mod)%mod+2LL+mod)%mod; } return 0; } int main(){ int m; Prime(); scanf("%d",&m); c0=1000000007;c1=1000000006;c2=500000002;c3=243900800;c4=79872000;c5=19660800;c6=5242880; c7=2097152; int n; while(m--){ scanf("%s",s+1);int len=strlen(s+1); printf("%lld\n",dfs(len,1e9+7)); } return 0; }
B DP
队友博客https://blog.csdn.net/qkoqhh/article/details/81267007
C 数位dp
队友博客https://blog.csdn.net/qkoqhh/article/details/81274954
D 构造 发现偶数项转移规律
#include<bits/stdc++.h> using namespace std; int a[205][205]; int n; void ycl() { a[1][1] = 0;a[1][2] = -1; a[2][1] = 1;a[2][2] = 1; for(int nn = 4;nn<=200;nn+=2) { for(int j = 1;j<=nn;j++) a[nn-1][j] = a[j][nn] = -1,a[nn][j] = a[j][nn-1] = 1; a[nn-1][nn-1] = 0; } return ; } int main() { ycl(); int _;cin>>_; while(_--) { cin>>n; if(n%2 == 1) cout<<"impossible"<<endl; else { cout<<"possible"<<endl; for(int i = 1;i<=n;i++) { for(int j = 1;j<=n;j++) { cout<<a[i][j]<<" "; } cout<<endl; } } } }
E 题意题 ....看懂题以后 发现是扫描线线段树板子题 不想写离散化的辣鸡写动态开点调了一天...然后是没有取膜也没开ll 做法还是很明显:动态开点+扫描线线段树
#include <bits/stdc++.h> using namespace std; #define ll long long const int MAXN=1e5+10; const ll mod=1e9+7; ll read(){ ll x=0,f=1;char ch=getchar(); while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();} while(isdigit(ch))x=x*10+ch-'0',ch=getchar(); return f*x; } ll ksm(ll a,ll b,ll c){ ll ans=1; while(b){ if(b&1)ans=ans*a%c; a=a*a%c;b=b>>1; } return ans; } typedef struct node{ int l,r;ll sum,flag; }node; node d[MAXN*25];int cnt;ll ans=0; void newnode(int &x,int len){x=++cnt;;d[x].l=d[x].r=0;d[x].sum=len;d[x].flag=1;} void up(int x,int l,int r){ int mid=(l+r)>>1; if(!d[x].l)d[x].sum=mid-l+1;else d[x].sum=d[d[x].l].sum*d[d[x].l].flag%mod; if(!d[x].r)d[x].sum+=r-mid;else d[x].sum+=d[d[x].r].sum*d[d[x].r].flag%mod; d[x].sum%=mod; } ll tag,tag1,vul1; void update(int &x,int l,int r,int ql,int qr,ll vul){ if(!x)newnode(x,r-l+1); if(ql<=l&&r<=qr){ d[x].flag=d[x].flag*tag1%mod; vul1=vul*d[x].flag%mod; ans=(ans+tag*(r-l+1)%mod)%mod; ans=(ans+((-1ll*((vul1*(tag*(d[x].sum%mod)%mod))%mod))%mod+mod)%mod)%mod; return ; } int mid=(l+r)>>1; if(ql<=mid)update(d[x].l,l,mid,ql,qr,vul*d[x].flag%mod); if(qr>mid) update(d[x].r,mid+1,r,ql,qr,vul*d[x].flag%mod); up(x,l,r); } int n; typedef struct Node{ ll x,y;ll vul; friend bool operator<(Node aa,Node bb){ if(aa.y==bb.y)return aa.x>bb.x; return aa.y>bb.y; } }Node; Node que[MAXN]; vector<int>vec; void slove(){ n=read();ll t1,t2;ll Xmax=-1,Ymax=-1;vec.clear();cnt=0;ans=0; for(int i=1;i<=n;i++)que[i].x=read(),que[i].y=read(),vec.push_back(que[i].y),t1=read(),t2=read(),Xmax=max(Xmax,que[i].x),Ymax=max(Ymax,que[i].y),que[i].vul=1ll*(t2-t1)*ksm(t2,mod-2,mod)%mod; sort(que+1,que+n+1);ll last=Xmax;tag=0;vec.push_back(0); sort(vec.begin(),vec.end()); int sz=unique(vec.begin(),vec.end())-vec.begin(); t1=sz-1;t2=sz-2; que[n+1].x=que[n+1].y=0; Ymax++; int tot=1;tag1=1ll;int rt=0; while(tot<=n){ tag=vec[t1]-vec[t2]; if(Xmax!=que[tot].x)update(rt,1,last,que[tot].x+1,Xmax,1ll);//cout<<que[tot].x+1<<"====="<<Xmax<<" "<<ans<<endl; Xmax=que[tot].x;tag1=tag1*que[tot].vul%mod; if(que[tot+1].y!=que[tot].y&&Xmax>=1){update(rt,1,last,1,Xmax,1ll);Xmax=0;} if(que[tot+1].y!=que[tot].y&&!Xmax){Xmax=last;tag1=1ll;t1=t2;t2--;} tot++; } printf("%lld\n",ans); } int main(){ int _;_=read(); while(_--){ slove(); } return 0; }
F 签到
#include<bits/stdc++.h> using namespace std; char maps[2005][2005]; int n,m; int main() { ios::sync_with_stdio(false); int T; cin>>T; while(T--) { cin>>n>>m; for(int i = 1;i<=n;i++) { for(int j = 1;j<=m;j++) cin>>maps[i][j]; } int heng= 0,shu = 0; for(int i = 1,j = n;i<j-1;i++,j--) { int flag = 0; for(int k = 1;k<=m/2;k++) { if(maps[i][k] != maps[i][m-k+1] || maps[j][k] !=maps[j][m-k+1]) { flag = 1; break; } } if(flag == 0) { heng++; } else break; } for(int i = 1,j=m;i<j-1;i++,j--) { int flag = 0; for(int k = 1;k<=n/2;k++) { if(maps[k][i] != maps[n-k+1][i] || maps[k][j] !=maps[n-k+1][j]) { flag = 1; break; } } if(flag == 0) { shu ++; } else break; } cout<<heng*shu<<endl; } }
G 贪心 二分前缀和即可
#include <bits/stdc++.h> const int MAXN=1e5+10; #define ll long long using namespace std; int d[MAXN],b[MAXN]; vector<int>vec; ll num[MAXN];int a[MAXN]; int main(){ int _;scanf("%d",&_); while(_--){ int n,m;scanf("%d%d",&n,&m); int t; for(int i=1;i<=n;i++)scanf("%d",&a[i]),vec.push_back(a[i]); sort(vec.begin(),vec.end()); int sz=unique(vec.begin(),vec.end())-vec.begin(); for(int i=1;i<=n;i++)a[i]=lower_bound(vec.begin(),vec.begin()+sz,a[i])-vec.begin()+1,d[a[i]]++; for(int i=1;i<=sz;i++)b[i]=d[i]; sort(d+1,d+sz+1); bool flag=0; for(int i=1;i<=sz;i++)num[i]=num[i-1]+d[i]; for(int i=sz-1;i>=0;i--){ int t=b[i+1]; int pos=lower_bound(d+1,d+sz+1,t)-d; ll num1=num[sz]-num[pos-1]-t; ll t1=num1-1ll*(t-1)*(sz-pos); if(t1<=m){flag=1;printf("%d\n",vec[i]);break;} } if(!flag)puts("-1"); vec.clear();memset(num,0,sizeof(num));memset(d,0,sizeof(d)); } }
J
一个比较神奇的题 首先明白每个不在对应位置的vul 他将收到一段区间的控制(具体是什么区间 自行理解) 如果这段区间最小值是-1 则是不存在的序列 然后想办法和这区间的点建图 但是明显 这个图建图是n^2的 考虑到分块的思想 结合线段树中的分块 我们按照线段树建树优化建图 通过拓扑解决问题(有环 则这个序列不成立)
#include <bits/stdc++.h> #define ll long long const int MAXN=2e5+10; const int inf=1e9+7; using namespace std; int read(){ int x=0,f=1;char ch=getchar(); while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();} while(isdigit(ch))x=x*10+ch-'0',ch=getchar(); return x*f; } int a[MAXN]; typedef struct node{ int id,vul; friend bool operator<(node aa,node bb){ return aa.vul>bb.vul; } }node; priority_queue<node>que; int dp[MAXN][21]; int n;int ma[MAXN]; int key[MAXN<<2]; vector<int>vec[MAXN<<2]; int pos[MAXN]; int du[MAXN<<2]; void built(int rt,int l,int r){ key[rt]=-1;du[rt]=0; if(l==r){pos[l]=rt;key[rt]=a[l];return ;} vec[rt<<1].clear();vec[rt<<1|1].clear(); vec[rt<<1].push_back(rt); vec[rt<<1|1].push_back(rt); du[rt]+=2; int mid=(l+r)>>1; built(rt<<1,l,mid); built(rt<<1|1,mid+1,r); } void update(int rt,int l,int r,int ql,int qr,int vis){ if(ql<=l&&r<=qr){vec[rt].push_back(vis);du[vis]++;return ;} int mid=(l+r)>>1; if(ql<=mid)update(rt<<1,l,mid,ql,qr,vis); if(qr>mid)update(rt<<1|1,mid+1,r,ql,qr,vis); } void st(){ for(int i=1;i<=n;i++)dp[i][0]=a[i]; for(int j=1;(1<<(j-1))<=n;j++){ for(int i=1;i+(1<<j)<=n+1;i++){ dp[i][j]=min(dp[i][j-1],dp[i+(1<<(j-1))][j-1]); } } } int rmq(int l,int r){ if(l>r)return inf; int k=ma[r-l+1];int k1=(1<<k); return min(dp[l][k],dp[r-k1+1][k]); } vector<int>ans; void bfs(){ for(int i=1;i<=n;i++){ if(!du[pos[i]]&&a[i]!=-1)que.push((node){pos[i],a[i]}); } if(que.empty())return ; while(!que.empty()){ node t=que.top();que.pop(); if(t.vul!=-1)ans.push_back(t.vul); for(int i=0;i<vec[t.id].size();i++){ du[vec[t.id][i]]--; if(!du[vec[t.id][i]])que.push((node){vec[t.id][i],key[vec[t.id][i]]}); } } for(int i=1;i<=n;i++){ if(du[pos[i]]){ ans.clear();break; } } } int main(){ ma[0]=-1; for(int i=1;i<MAXN;i++)if((i&(i-1))==0)ma[i]=ma[i-1]+1;else ma[i]=ma[i-1]; int _;_=read(); while(_--){ n=read();ans.clear(); while(!que.empty())que.pop(); //memset(num,0,sizeof(num)); int cnt=0; for(int i=1;i<=n;i++)a[i]=read(); built(1,1,n); st();bool flag=0; for(int i=1;i<=n;i++){ if(a[i]==-1)continue; cnt++; if(a[i]%n==i-1){continue;} int t1=a[i]%n+1; if(i>t1){ int t2=rmq(t1,i-1); if(t2==-1){flag=1;break;} update(1,1,n,t1,i-1,pos[i]); } else{ int t2=min(rmq(t1,n),rmq(1,i-1)); if(t2==-1){flag=1;break;} update(1,1,n,t1,n,pos[i]); if(i!=1)update(1,1,n,1,i-1,pos[i]); } } if(!cnt){puts("");continue;} if(flag){puts("-1");continue;} bfs(); if(ans.size()<cnt){puts("-1");continue;} for(int i=0;i<ans.size();i++){ if(i==0)printf("%d",ans[i]); else printf(" %d",ans[i]); } printf("\n"); } return 0; }