【noip2017】
D1T1 小凯的诱惑疑惑
证明:链接
不妨设 a<b 假设答案为 x
若x ≡ ma (mod b) (1 ≤ m ≤ b − 1)
即x = ma + nb (1 ≤ m ≤ b − 1)
显然当n ≥ 0 时 x 可以用a,b表示出来
因此当 n=−1 时 x 取得最大值,此时 x = ma − b
显然当 m 取得最大值 b − 1时 x 最大,此时 x=(b−1)a−b=ab−a−b
因此 a, b 所表示不出的最大的数是 ab−a−b
(超小声bb)这个比较好理解 还有注意要输出long long 就很难受,不开long long 是60
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 /* 2 id:gww 3 language: 4 啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊 5 */ 6 #include<bits/stdc++.h> 7 using namespace std; 8 long long read() //This is 读入优化 9 { 10 long long x=0,w=0;char ch=0; 11 while(!isdigit(ch)) {w|=ch=='-';ch=getchar();} 12 while(isdigit(ch)) x=(x<<3)+(x<<1)+(ch^48),ch=getchar(); 13 return w?-x:x; 14 } 15 16 int main() 17 { 18 long long a,b; 19 a=read(),b=read(); 20 printf("%lld",(a*b)-a-b); 21 return 0; 22 }
D1T2 时间复杂度
这个模拟太恶心了,靠死不想模拟了 好像是因为中间夹杂了我的莫名其妙的判断ERR导致爆炸 还有我莫名其妙的输入
对于 30%的数据:不存在语法错误,数据保证小明给出的每个程序的前 L/2 行一定为以 F
开头的语句,第 L/2+1行至第 L 行一定为以 E 开头的语句,L≤10,若 x、y 均 为整数,x一定小于 y,且只有 y 有可能为 n。
对于 50%的数据:不存在语法错误,L≤100,且若 x、y 均为整数,x 一定小于 y, 且只有 y 有可能为 n。
对于 70%的数据:不存在语法错误,L≤100。
对于 100%的数据:L≤100。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 /* 2 id:gww 3 language: 4 啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊 5 */ 6 #include<bits/stdc++.h> 7 using namespace std; 8 const int N=100000+2; 9 const int M=200000+2; 10 const int inf=0x3f3f3f3f; 11 char a[105],dm[1002],ii[105]; 12 int l,nn; 13 int read() 14 { 15 int w=0,x=0;char ch=0; 16 while(!isdigit(ch)) w|=ch=='-',ch=getchar(); 17 while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar(); 18 return w?-x:x; 19 } 20 21 void clean() 22 { 23 l=nn=0; 24 memset(dm,0,sizeof(dm)); 25 } 26 27 int main() 28 { 29 int t=read(); 30 while(t--) 31 { 32 clean(); 33 scanf("%d %s",&l,a+1); 34 int la=strlen(a+1),on=0,pn=0,nnn=0; 35 bool dx=0,xt=0; 36 for(int i=1;i<=la;i++) 37 { 38 if(a[i]>='0'&&a[i]<='9') 39 on=on*10+a[i]-'0'; 40 if(a[i]=='n') 41 pn=1; 42 } 43 if(1&l) 44 { 45 printf("ERR\n"); 46 for(int i=0;i<=l;i++) 47 gets(dm); 48 } 49 for(int i=0;i<=l;i++) 50 { 51 gets(dm); 52 int ldm=strlen(dm); 53 int x=0,y=0; 54 if(dm[0]=='E') nnn=0; 55 if(dm[0]!='E') 56 { 57 ii[i]=dm[2]; 58 bool k=0,xn=0; 59 for(int j=4;j<=ldm;j++) 60 { 61 if(dm[j]>='0'&&dm[j]<='9') 62 { 63 if(k==0) x=x*10+dm[j]-'0'; 64 else y=y*10+dm[j]-'0'; 65 } 66 if(dm[j]==' ') k=1; 67 if(x!=0&&k==1&&dm[j]=='n') {nnn++;break;} 68 if(x==0&&k==0&&dm[j]=='n') {xn=1;break;} 69 } 70 if(x>y&&nn==0) dx=1; 71 } 72 nn=max(nn,nnn); 73 } 74 sort(ii+1,ii+1+l); 75 char iii=ii[1]; 76 if(pn==1&&on==nn) printf("Yes\n"); 77 if(pn==0&&on==1) printf("Yes\n"); 78 if(pn==1&&on!=nn) printf("No\n"); 79 } 80 return 0; 81 }
待写出正解
D1T3 逛公园
先spfa跑一遍跑出最短路,然后再反向建图,跑dfs记忆化搜索
具体题解
我的20分淳朴dfs+spfaQAQ
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 /* 2 id:gww 3 language: 4 啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊 5 */ 6 #include<bits/stdc++.h> 7 using namespace std; 8 const int N=100000+2; 9 const int M=200000+2; 10 const int inf=0x3f3f3f3f; 11 int n,m,k,p,dis[N],s,ans=0; 12 int head[M],cnt=0; 13 bool vis[N]; 14 int read() 15 { 16 int w=0,x=0;char ch=0; 17 while(!isdigit(ch)) w|=ch=='-',ch=getchar(); 18 while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar(); 19 return w?-x:x; 20 } 21 22 struct lxyy 23 { 24 int u,v,w,nxt; 25 }e[M]; 26 void add(int u,int v,int w) 27 { 28 e[++cnt].u=u; 29 e[cnt].v=v; 30 e[cnt].w=w; 31 e[cnt].nxt=head[u]; 32 head[u]=cnt; 33 } 34 void clean() 35 { 36 ans=0; 37 memset(head,0,sizeof(head)); 38 memset(vis,0,sizeof(vis)); 39 memset(dis,inf,sizeof(dis)); 40 } 41 42 queue<int> q; 43 void spfa(int u) 44 { 45 q.push(u),dis[u]=0,vis[u]=1; 46 while(!q.empty()) 47 { 48 u=q.front(); 49 q.pop(),vis[u]=0; 50 for(int i=head[u];i!=0;i=e[i].nxt) 51 { 52 int v=e[i].v,w=e[i].w; 53 if(dis[v]>dis[u]+w) 54 { 55 dis[v]=dis[u]+w; 56 if(vis[v]==0) 57 { 58 q.push(v); 59 vis[v]=1; 60 } 61 } 62 } 63 } 64 } 65 66 void dfs(int nw,int ti) 67 { 68 if(ti>s) return; 69 if(nw==n) {ans++;ans%=p;return;} 70 for(int i=head[nw];i!=0;i=e[i].nxt) 71 { 72 int v=e[i].v,w=e[i].w; 73 if(ti+w>s) continue; 74 dfs(v,ti+w); 75 } 76 } 77 78 int main() 79 { 80 int t=read(); 81 while(t--) 82 { 83 clean(); 84 n=read(),m=read(),k=read(),p=read(); 85 for(int i=1;i<=m;i++) 86 { 87 int u=read(),v=read(),w=read(); 88 add(u,v,w); 89 } 90 spfa(1);s=dis[n]+k; 91 dfs(1,0); 92 printf("%d\n",ans%p); 93 } 94 return 0; 95 }
spfa+反向建图跑dfs判断零环
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 /* 2 id:gww 3 language: 4 啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊 5 */ 6 #include<bits/stdc++.h> 7 using namespace std; 8 const int N=100000+2; 9 const int M=200000+2; 10 const int inf=0x3f3f3f3f; 11 int n,m,k,p,dis[N],s,ans=0; 12 int head[M],cnt=0; 13 int dp[N][52],in[N][52];//dp[i][k]表示比i-u最短路径多k有多少条 14 bool vis[N],fla; 15 int read() 16 { 17 int w=0,x=0;char ch=0; 18 while(!isdigit(ch)) w|=ch=='-',ch=getchar(); 19 while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar(); 20 return w?-x:x; 21 } 22 23 struct lxyy 24 { 25 int u,v,w,nxt; 26 }e[M]; 27 void add(int u,int v,int w,int cnt) 28 { 29 e[cnt].u=u; 30 e[cnt].v=v; 31 e[cnt].w=w; 32 e[cnt].nxt=head[u]; 33 head[u]=cnt; 34 } 35 void clean() 36 { 37 ans=0,fla=0; 38 memset(head,0,sizeof(head)); 39 memset(vis,0,sizeof(vis)); 40 memset(dis,inf,sizeof(dis)); 41 memset(dp,0,sizeof(dp)); 42 memset(in,0,sizeof(in)); 43 } 44 45 queue<int> q; 46 void spfa() 47 { 48 q.push(1),dis[1]=0,vis[1]=1; 49 while(!q.empty()) 50 { 51 int u=q.front(); 52 q.pop(),vis[u]=0; 53 for(int i=head[u];i!=0;i=e[i].nxt) 54 { 55 int v=e[i].v,w=e[i].w; 56 if(dis[v]>dis[u]+w) 57 { 58 dis[v]=dis[u]+w; 59 if(vis[v]==0) 60 { 61 vis[v]=1; 62 q.push(v); 63 } 64 } 65 } 66 } 67 } 68 69 int dfs(int nw, int ti) 70 { 71 if (in[nw][ti] == 1 || fla) return fla = 1; 72 if (in[nw][ti] == 2) return dp[nw][ti]; 73 in[nw][ti] = 1; // 74 for (int i = head[nw]; i; i = e[i].nxt) 75 { 76 int v=e[i].v; 77 int w = ti+dis[nw]-dis[v]-e[i].w; 78 if (w>k||w<0) continue; 79 dp[nw][ti]+=dfs(v, w); 80 dp[nw][ti]%=p; 81 } 82 in[nw][ti]=2; //设置该点曾经访问过 83 return dp[nw][ti]; //回溯答案 84 } 85 86 int main() 87 { 88 int t=read(); 89 while(t--) 90 { 91 clean(); 92 n=read(),m=read(),k=read(),p=read(); 93 for(int i=1;i<=m;i++) 94 { 95 int u=read(),v=read(),w=read(); 96 add(u,v,w,i); 97 } 98 spfa(); 99 memset(head,0,sizeof(head)); 100 for(int i=1;i<=m;i++)//反向建图 可以对照着add来理解 101 { 102 swap(e[i].u,e[i].v); 103 e[i].nxt=head[e[i].u]; 104 head[e[i].u]=i; 105 } 106 dp[1][0]=1; 107 for(int i=0;i<=k;i++) 108 { 109 ans+=dfs(n,i); 110 ans%=p; 111 } 112 if(fla==1) printf("-1\n"); 113 else printf("%d\n",ans%p); 114 } 115 return 0; 116 }
D2T1奶酪
我用的搜索,从最下面那个连通奶酪开始搜(我忘了并查集了)
最最最重要就是记得开long long分不清哪要开long long就全都开,我昨天打的时候忘了给快读加long longQAQ
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 /* 2 id:gww 3 language: 4 啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊 5 */ 6 #include<bits/stdc++.h> 7 using namespace std; 8 #define ll long long 9 const int N=1000+5; 10 ll n,h,r; 11 bool vis[N],ans; 12 13 ll read() 14 { 15 ll x=0,w=0;char ch=0; 16 while(!isdigit(ch)) w|=ch=='-',ch=getchar(); 17 while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar(); 18 return w?-x:x; 19 } 20 struct lxyy 21 { 22 ll x,z,y; 23 }e[N]; 24 25 ll jud(ll x1,ll x2,ll y1,ll y2,ll z1,ll z2) 26 { 27 ll xx=x1-x2,yy=y1-y2,zz=z1-z2; 28 ll sum=xx*xx+yy*yy+zz*zz; 29 return sum; 30 } 31 32 void dfs(ll x,ll y,ll z,int cnt) 33 { 34 if(z+r>=h) 35 { 36 ans=1; 37 return; 38 } 39 vis[cnt]=1; 40 for(int i=1;i<=n;i++) 41 if(vis[i]==0&&jud(x,e[i].x,y,e[i].y,z,e[i].z)<=4*r*r) 42 dfs(e[i].x,e[i].y,e[i].z,i); 43 } 44 45 int main() 46 { 47 int t=read(); 48 while(t--) 49 { 50 memset(vis,0,sizeof(vis)); 51 ans=0; 52 n=read(),h=read(),r=read(); 53 for(int i=1;i<=n;i++) 54 e[i].x=read(),e[i].y=read(),e[i].z=read(); 55 for(int i=1;i<=n;i++) 56 { 57 if(ans==1) break; 58 if(r-e[i].z>=0) 59 dfs(e[i].x,e[i].y,e[i].z,i); 60 } 61 if(ans==1) printf("Yes\n"); 62 else printf("No\n"); 63 } 64 return 0; 65 }
D2T1 宝藏
看数据就可以看出来是状压dp,可是我太弱了 想不出来转移方程
作为一个蒟蒻肯定满脑子都是暴力暴力暴力暴力 我们就学过一个高大上(并不) 实用的算法—dfs
好吧是我昨天想了半天之后选择看题解,然后发现了dfs+状压,好理解又好写(最适合我这种蒟蒻了) 状压真的超级有趣
cnt[]表示到到起点的距离 dp[state]表示状态为state时的最少花费,然后就一个洞一个洞地打,找最优解
能跑过大概是因为dp状态的更新有条件
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 /* 2 id:gww 3 language: 4 啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊 5 */ 6 #include<bits/stdc++.h> 7 using namespace std; 8 const int N=15; 9 const int M=1000+5; 10 const int inf=0x3f3f3f3f; 11 int n,m,ans=inf,r[N][N]; 12 int dp[1<<N],cnt[N]; 13 14 int read() 15 { 16 int w=0,x=0;char ch=0; 17 while(!isdigit(ch)) w|=ch=='-',ch=getchar(); 18 while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar(); 19 return w?-x:x; 20 } 21 22 void startt() 23 { 24 n=read(),m=read(); 25 for(int i=1;i<=n;i++) 26 for(int j=1;j<=n;j++) 27 r[i][j]=inf;//初始化 28 for(int i=1;i<=m;i++) 29 { 30 int x=read(),y=read(),w=read(); 31 r[x][y]=r[y][x]=min(w,r[x][y]); 32 } 33 } 34 35 void clean() 36 { 37 for(int i=1;i<=n;i++) 38 cnt[i]=inf; 39 for(int i=1;i<=(1<<n);i++) 40 dp[i]=inf; 41 } 42 43 void dfs(int x) 44 { 45 for(int i=1;i<=n;i++) 46 if(x&(1<<(i-1)))//被开发过的宝藏屋 47 { 48 for(int j=1;j<=n;j++) 49 if(!((1<<(j-1))&x)&&r[i][j]!=inf)//枚举相连的 未开发的宝藏屋 50 { 51 int neww=x|(1<<(j-1)); 52 if(dp[neww]>dp[x]+r[i][j]*cnt[i]) 53 { 54 int wa=cnt[j]; 55 dp[neww]=dp[x]+r[i][j]*cnt[i]; 56 cnt[j]=cnt[i]+1; 57 dfs(neww); 58 cnt[j]=wa;//回溯操作! 59 } 60 } 61 62 } 63 } 64 65 int main() 66 { 67 startt(); 68 for(int i=1;i<=n;i++)//枚举每一个洞 69 { 70 clean(); 71 cnt[i]=1,dp[(1<<(i-1))]=0; 72 dfs(1<<(i-1)); 73 ans=min(ans,dp[(1<<n)-1]); 74 } 75 printf("%d",ans); 76 return 0; 77 }
D2T1 列队
(总是说成队列)
靠死想不出来这个,看题解看到线段树、splay、树状数组什么的,我选择死亡
其实暑假的时候线段树都没怎么消化(我懂了,我这就滚去练线段树)
我的30分模拟
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 /* 2 id:gww 3 language: 4 啊啊啊啊啊啊啊啊啊啊啊啊啊 5 */ 6 #include<bits/stdc++.h> 7 using namespace std; 8 const int N=1000+5; 9 const int Q=500+5; 10 int n,m,q; 11 int las[N],h[N],pos[1005][1005]; 12 13 int read() 14 { 15 int x=0,w=0;char ch=0; 16 while(!isdigit(ch)) w|=ch=='-',ch=getchar(); 17 while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar(); 18 return w?-x:x; 19 } 20 21 struct lxyy 22 { 23 int x,y; 24 }e[N]; 25 26 int main() 27 { 28 n=read(),m=read(),q=read(); 29 for(int i=1;i<=q;i++) 30 { 31 e[i].x=read(),e[i].y=read(); 32 } 33 for(int i=1;i<=n;i++) 34 for(int j=1;j<=m;j++) 35 pos[i][j]=(i-1)*m+j; 36 for(int i=1;i<=q;i++) 37 { 38 long long ans; 39 ans=(long long)pos[e[i].x][e[i].y]; 40 printf("%lld\n",ans); 41 for(int j=e[i].y;j<=m-1;j++)//向左看齐 42 pos[e[i].x][j]=pos[e[i].x][j+1]; 43 pos[e[i].x][m]=pos[e[i].x+1][m]; 44 for(int j=e[i].x;j<n;j++)//向前看齐 45 pos[j][m]=pos[j+1][m]; 46 pos[n][m]=ans; 47 } 48 return 0; 49 }
昨晚还看了一个50分的,然后自己理解着也写了差不多的,今天一考我就忘了50分这个怎么写,最后向模拟屈服
因为一次就出一个人,然后就只改变出去的当前行和最后一列 所以!我们就只用研究改变行和最后一列 然后就50昏!
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 /* 2 id:gww 3 language: 4 啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊 5 */ 6 #include<bits/stdc++.h> 7 using namespace std; 8 #define ll long long 9 const int N=50002; 10 int n,m,q,tot; 11 ll las[N],h[N],pos[501][N]; 12 ll ans; 13 14 int read() 15 { 16 int w=0,x=0;char ch=0; 17 while(!isdigit(ch)) w|=ch=='-',ch=getchar(); 18 while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar(); 19 return w?-x:x; 20 } 21 struct lxyy 22 { 23 int x,y; 24 }e[N]; 25 26 int main() 27 { 28 n=read();m=read();q=read(); 29 for(int i=1;i<=q;i++) 30 { 31 e[i].x=read();e[i].y=read(); 32 h[i]=e[i].x;//改变的横坐标 33 } 34 for(int i=1;i<=n;i++) 35 las[i]=las[i-1]+m;//最后一列编号 36 sort(h+1,h+q+1);//去重之前要排序 37 tot=unique(h+1,h+q+1)-h-1;//去重之后原数组只剩下tot大小 38 ll t; 39 for(int i=1;i<=tot;i++) 40 { 41 t=(ll)(h[i]-1)*m; 42 for(int j=1;j<=m;j++) 43 pos[i][j]=++t;//给每一行每一列都标上号 44 } 45 int xx; 46 for(int i=1;i<=q;i++) 47 { 48 for(int j=1;j<=tot;j++) 49 if(h[j]==e[i].x)//寻找e[i].x在h数组中的位置 50 {nx=j;break;} 51 if(e[i].y==m)//如果出队的这个人在最后一列 52 ans=last[h[nx]]; 53 else ans=pos[nx][e[i].y]; 54 printf("%lld\n",ans); 55 if(e[i].y!=m)//向左看齐 56 { 57 for(int j=e[i].y;j<m-1;j++) 58 pos[nx][j]=pos[nx][j+1]; 59 pos[nx][m-1]=last[h[nx]]; 60 } 61 for(int j=h[nx];j<n;++j)//向前看齐 62 last[j]=last[j+1]; 63 last[n]=ans;//归队 64 } 65 return 0; 66 }
QAQ等我什么时候会了满分的再添
还是我太弱了