牛客网暑期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;
}

浙公网安备 33010602011771号