又快要到省赛了,补一补去年的题的,话说当时还没补过...
断断续续,两天写了8道,剩下两道应该是防AK的,去年榜首也是8道*2.剩下两道随缘补吧。
补题OJ:ZZULI
A-计划日(模拟)
题目链接:http://acm.zzuli.edu.cn/problem.php?id=2304
题目大意:略。
思路:照着模拟就行了。注意输出的时候02不是2
ACCode:
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<map>
#include<set>
#include<deque>
#include<queue>
#include<stack>
#include<bitset>
#include<string>
#include<fstream>
#include<iostream>
#include<algorithm>
using namespace std;
#define ll long long
#define Pair pair<int,ll>
//#define max(a,b) (a)>(b)?(a):(b)
//#define min(a,b) (a)<(b)?(a):(b)
#define clean(a,b) memset(a,b,sizeof(a))
//std::ios::sync_with_stdio(false);
// register
const int MAXN=1e5+10;
const int INF32=0x3f3f3f3f;
const ll INF64=0x3f3f3f3f3f3f3f3f;
const ll mod=1e9+7;
const double EPS=1.0e-8;
const double PI=acos(-1.0);
int mon29[13]={0,31,29,31,30,31,30,31,31,30,31,30,31};
int mon28[13]={0,31,28,31,30,31,30,31,31,30,31,30,31};
int main(){
int T;scanf("%d",&T);
while(T--){
char s[10],ch=getchar();int day,n;
scanf("%s%d%d",&s,&day,&n);
int yy=0,mm=0,dd=0;
for(int i=0;i<4;++i) yy=yy*10+s[i]-'0';
for(int i=4;i<=5;++i) mm=mm*10+s[i]-'0';
for(int i=6;i<=7;++i) dd=dd*10+s[i]-'0';
for(int i=1;i<=n;++i){
day=(day%7)+1;
dd++;
if(yy%4==0){
if(dd>mon29[mm]){
dd=1;mm++;
}
if(mm>12){
mm=1;yy++;
}
}
else{
if(dd>mon28[mm]){
dd=1;mm++;
}
if(mm>12){
mm=1;yy++;
}
}
}printf("%04d%02d%02d %d\n",yy,mm,dd,day);
}
}
/*
*/
B-治安管理(思维)
题目链接:http://acm.zzuli.edu.cn/problem.php?id=2305
题目大意:略。
思路:之前CF写过一道类似的。碰到起点+1,终点-1,就行了。(去年打的时候什么都不会,胡乱暴力竟然过了??)
ACCode:
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<map>
#include<set>
#include<deque>
#include<queue>
#include<stack>
#include<bitset>
#include<string>
#include<fstream>
#include<iostream>
#include<algorithm>
using namespace std;
#define ll long long
#define Pair pair<int,ll>
//#define max(a,b) (a)>(b)?(a):(b)
//#define min(a,b) (a)<(b)?(a):(b)
#define clean(a,b) memset(a,b,sizeof(a))
//std::ios::sync_with_stdio(false);
// register
const int MAXN=1e5+10;
const int INF32=0x3f3f3f3f;
const ll INF64=0x3f3f3f3f3f3f3f3f;
const ll mod=1e9+7;
const double EPS=1.0e-8;
const double PI=acos(-1.0);
int Vis[MAXN];
int main(){
int T;scanf("%d",&T);
while(T--){
clean(Vis,0);
int n,m,a,b;scanf("%d%d%d%d",&n,&m,&a,&b);
for(int i=1;i<=n;++i){
int x;scanf("%d",&x);
Vis[x]++;
}
for(int i=1;i<=n;++i){
int x;scanf("%d",&x);
Vis[x]--;
}int flag=1,num=0,maxx=0,minn=INF32;
// for(int i=a;i<=b;++i) cout<<i<<" : "<<Vis[i]<<endl;
for(int i=0;i<a;++i) num+=Vis[i];
for(int i=a;i<b;++i){
num+=Vis[i];
maxx=max(maxx,num);
minn=min(minn,num);
// cout<<num<<" "<<maxx<<" "<<minn<<endl;
if(num<m){
flag=0;
}
}
if(flag==0) printf("NO %d\n",minn);
else printf("YES %d\n",maxx);
}
}
/*
*/
C-山区修路(DP)
题目链接:http://acm.zzuli.edu.cn/problem.php?id=2306
题目大意:略
思路:这一看就是DP 啊,没毛病,但是状态转移方程是什么?一开始是想枚举所有的n*100*100的情况,但1e9的复杂度很让我害怕,后来实在找不到好的方法,就试着交了发,没想到竟然过了??(但是我深知代码丑陋,因此若有大佬路过,请务必留言告诉我更快的方法/谢过)
ACCode:
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<map>
#include<set>
#include<deque>
#include<queue>
#include<stack>
#include<bitset>
#include<string>
#include<fstream>
#include<iostream>
#include<algorithm>
using namespace std;
#define ll long long
#define Pair pair<int,ll>
//#define max(a,b) (a)>(b)?(a):(b)
//#define min(a,b) (a)<(b)?(a):(b)
#define clean(a,b) memset(a,b,sizeof(a))
//std::ios::sync_with_stdio(false);
// register
const int MAXN=1e3+10;
const int INF32=0x3f3f3f3f;
const ll INF64=0x3f3f3f3f3f3f3f3f;
const ll mod=1e9+7;
const double EPS=1.0e-8;
const double PI=acos(-1.0);
int dp[MAXN][110],a[MAXN];
int n,x;
int main(){
std::ios::sync_with_stdio(false);
int T;cin>>T;
while(T--){
cin>>n>>x;clean(dp,INF32);
for(int i=1;i<=n;++i) cin>>a[i];
for(int i=a[1];i<=100;++i) dp[1][i]=(i-a[1])*(i-a[1]);
for(int i=2;i<=n;++i){
for(int j=a[i];j<=100;++j){
for(int k=a[i-1];k<=100;++k){
dp[i][j]=min(dp[i][j],dp[i-1][k]+((j-a[i])*(j-a[i]))+abs(j-k)*x);
}
}
}int ans=INF32;
for(int i=0;i<=100;++i) ans=min(ans,dp[n][i]);
cout<<ans<<endl;
}
}
/*
*/
D-求XF+闭包(读题+暴力)
题目链接:http://acm.zzuli.edu.cn/problem.php?id=2307
题目大意:就是给你一个全集U,一个集合A,给你一些关系F,让你从A和F中推出所有的能得到的元素B,按字典序输出即可。
思路:因为只有26个字符,因此直接循环枚举即可。
ACCode:
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<map>
#include<set>
#include<deque>
#include<queue>
#include<stack>
#include<bitset>
#include<string>
#include<fstream>
#include<iostream>
#include<algorithm>
using namespace std;
#define ll long long
#define Pair pair<int,int>
//#define max(a,b) (a)>(b)?(a):(b)
//#define min(a,b) (a)<(b)?(a):(b)
#define clean(a,b) memset(a,b,sizeof(a))// ??
//std::ios::sync_with_stdio(false);
// register
const int MAXN=1e2+10;
const int INF32=0x3f3f3f3f;
const ll INF64=0x3f3f3f3f3f3f3f3f;
const ll mod=1e9+7;
const double PI=acos(-1.0);
const double EPS=1.0e-8;
int Vis[30],Use[30];
string F1[30],F2[30];
int main(){
std::ios::sync_with_stdio(false);
int T;cin>>T;
while(T--){
clean(Vis,0);clean(Use,0);
int n,m,k;cin>>n>>m>>k;
string U,X;
cin>>U>>X;
int lenU=U.size(),lenX=X.size();
for(int i=0;i<lenX;++i) Vis[X[i]-'A']=1;
for(int i=1;i<=k;++i){
cin>>F1[i]>>F2[i];
}
int flag=1;
while(flag){
flag=0;
for(int i=1;i<=k;++i){
if(Use[i]) continue;
int change=1;
for(int j=0;j<F1[i].size();++j){
if(Vis[F1[i][j]-'A']==0){
change=0;break;
}
}
if(change){
for(int j=0;j<F2[i].size();++j){
Vis[F2[i][j]-'A']=1;
}Use[i]=1;flag=1;
}
}
}
for(int i=0;i<26;++i){
if(Vis[i]) cout<<char(i+'A');
}cout<<endl;
}
}
E-物流配送(最小费用流)
题目链接:http://acm.zzuli.edu.cn/problem.php?id=2308
题目大意:略。
思路:又是一眼能够看出板子的题。一开始想着拆点建图,后来画了画,发现根本没必要,直接连就好了,赤裸裸的板子。
画图(样例):然后跑一波费用流就好了,输出最小费用。
ACCode:
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<map>
#include<set>
#include<deque>
#include<queue>
#include<stack>
#include<bitset>
#include<string>
#include<fstream>
#include<iostream>
#include<algorithm>
using namespace std;
#define ll long long
#define Pair pair<int,ll>
//#define max(a,b) (a)>(b)?(a):(b)
//#define min(a,b) (a)<(b)?(a):(b)
#define clean(a,b) memset(a,b,sizeof(a))
//std::ios::sync_with_stdio(false);
// register
const int MAXN=1e3+10;
const int INF32=0x3f3f3f3f;
const ll INF64=0x3f3f3f3f3f3f3f3f;
const ll mod=1e9+7;
const double EPS=1.0e-8;
const double PI=acos(-1.0);
struct Node{
int v,w,cost,nxt;
Node(int _v=0,int _w=0,int _cost=0,int _nxt=0){
v=_v;w=_w;cost=_cost;nxt=_nxt;
}
};
Node Edge[MAXN<<2];
int Head[MAXN],Ecnt;
int Dis[MAXN],Vis[MAXN];
int Pre[MAXN],Flow[MAXN],Last[MAXN];
int n,S,T;
void Intt(){
clean(Head,-1);Ecnt=0;
}
void Add(int u,int v,int w,int cost){
Edge[Ecnt]=Node(v,w,cost,Head[u]);
Head[u]=Ecnt++;
Edge[Ecnt]=Node(u,0,-cost,Head[v]);
Head[v]=Ecnt++;
}
int SPFA(){
clean(Vis,0);Vis[S]=1;
clean(Dis,INF32);Dis[S]=0;
Flow[S]=INF32;Pre[T]=-1;
queue<int> que;que.push(S);
while(que.size()){
int u=que.front();que.pop();
Vis[u]=0;
for(int i=Head[u];i+1;i=Edge[i].nxt){
int temp=Edge[i].v;
if(Edge[i].w>0&&Dis[temp]>Dis[u]+Edge[i].cost){
Dis[temp]=Dis[u]+Edge[i].cost;
Flow[temp]=min(Flow[u],Edge[i].w);
Last[temp]=i;Pre[temp]=u;
if(Vis[temp]==0){
Vis[temp]=1;que.push(temp);
}
}
}
}return Dis[T]==INF32?0:1;
}
void MCMF(){
int maxw=0,mincost=0;
while(SPFA()){
int u=T;
maxw+=Flow[T];
mincost+=Dis[T]*Flow[T];
while(u!=S){
Edge[Last[u]].w-=Flow[T];
Edge[Last[u]^1].w+=Flow[T];
u=Pre[u];
}
}printf("%d\n",mincost);
}
int main(){
Intt();
scanf("%d",&n);
int x;S=0,T=n+1;
for(int i=1;i<=n;++i){
scanf("%d",&x);
Add(S,i,x,0);
}
for(int i=1;i<=n;++i){
scanf("%d",&x);
Add(i,T,x,0);
}int a,b,v;
for(int i=1;i<n;++i){
scanf("%d%d%d",&a,&b,&v);
Add(a,b,INF32,v);Add(b,a,INF32,v);
}MCMF();
}
/*
*/
F-Gene mutation(读题+暴力)
题目链接:http://acm.zzuli.edu.cn/problem.php?id=2309
题目大意:给出n个元素的数组a,和m元素的数组b。然后判断a中有多少组连续元素能够转化成b。
能够转化的意思为:对应位置元素相减相等。顺序可以打乱。
思路:由于给定数据非常小,因此直接暴力枚举每个位置作为起点即可。对b数组进行排序,然后每组小数组也排序,比较即可。
但是由于OJ的问题(输入数据和输出数据是相同的,就写了份表面AC的代码,等有机会在测试吧)
Code:
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<map>
#include<set>
#include<deque>
#include<queue>
#include<stack>
#include<bitset>
#include<string>
#include<fstream>
#include<iostream>
#include<algorithm>
using namespace std;
#define ll long long
#define Pair pair<int,int>
//#define max(a,b) (a)>(b)?(a):(b)
//#define min(a,b) (a)<(b)?(a):(b)
#define clean(a,b) memset(a,b,sizeof(a))// ??
//std::ios::sync_with_stdio(false);
// register
const int MAXN=2e4+10;
const int INF32=0x3f3f3f3f;
const ll INF64=0x3f3f3f3f3f3f3f3f;
const ll mod=1e9+7;
const double PI=acos(-1.0);
const double EPS=1.0e-8;
int a[MAXN],b[15],c[15];
int n,m;
int main(){
int T;scanf("%d",&T);
while(T--){
scanf("%d",&n);
for(int i=0;i<n;++i) scanf("%d",&a[i]);
scanf("%d",&m);
for(int i=0;i<m;++i) scanf("%d",&b[i]);
sort(b,b+m);
// for(int i=1;i<=m;++i) cout<<b[i]<<" ";
int cnt=0;
for(int i=0;i<=n-m;++i){
for(int j=i;j<m+i;++j) c[j-i]=a[j];
sort(c,c+m);
// for(int j=1;j<=m;++j) cout<<c[j]<<" ";cout<<endl;
int ad=c[0]-b[0],flag=1;
for(int j=0;j<m;++j){
// cout<<c[j]<<" "<<b[j]<<endl;
if(ad!=(c[j]-b[j])){
flag=0;break;
}
}//cout<<"---"<<endl;
if(flag) cnt++;
}printf("%d\n",cnt);
}
}
G-Checkpoints(最短路)
题目链接:http://acm.zzuli.edu.cn/problem.php?id=2310
题目大意:给出n个点,m个单向边,起点S和终点T,求S到T 的最短距离
思路:直接建完图之后跑Dijkstra,但是不知道为什么比赛的时候都WA了。。。
ACCode:
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<map>
#include<set>
#include<deque>
#include<queue>
#include<stack>
#include<bitset>
#include<string>
#include<fstream>
#include<iostream>
#include<algorithm>
using namespace std;
#define ll long long
#define Pair pair<int,int>
#define M_P(a,b) make_pair(a,b)
//#define max(a,b) (a)>(b)?(a):(b)
//#define min(a,b) (a)<(b)?(a):(b)
#define clean(a,b) memset(a,b,sizeof(a))
//std::ios::sync_with_stdio(false);
// register
const int MAXN=1e2+10;
const int INF32=0x3f3f3f3f;
const ll INF64=0x3f3f3f3f3f3f3f3f;
const ll mod=1e9+7;
const double EPS=1.0e-8;
const double PI=acos(-1.0);
struct Node{
int v,val,nxt;
Node(int _v=0,int _val=0,int _nxt=0){
v=_v;val=_val;nxt=_nxt;
}
};
Node Edge[MAXN<<2];
int Head[MAXN],Ecnt;
int Vis[MAXN],Dis[MAXN];
int n,m,S,T;
struct Cmp{
int operator ()(const Pair &a,const Pair &b){
return a.second>b.second;
}
};
void Intt(){
clean(Head,-1);Ecnt=0;
}
void Add(int u,int v,int val){
Edge[Ecnt]=Node(v,val,Head[u]);
Head[u]=Ecnt++;
}
void Dijkstra(){
clean(Vis,0);
clean(Dis,INF32);Dis[S]=0;
priority_queue<Pair,vector<Pair>,Cmp> que;que.push(M_P(S,0));
while(que.size()){
Pair u=que.top();que.pop();
if(Vis[u.first]) continue;
Vis[u.first]=1;
for(int i=Head[u.first];i+1;i=Edge[i].nxt){
int temp=Edge[i].v;
if(Dis[temp]>Dis[u.first]+Edge[i].val){
Dis[temp]=Dis[u.first]+Edge[i].val;
que.push(M_P(temp,Dis[temp]));
}
}
}
}
int main(){
int Case;scanf("%d",&Case);
while(Case--){
Intt();
scanf("%d%d%d%d",&n,&m,&S,&T);
int a,b;
for(int i=1;i<=m;++i){
scanf("%d%d",&a,&b);
Add(a,b,1);
}Dijkstra();
printf("%d\n",Dis[T]);
}
}
/*
*/
H-Attack City and Capture Territory(博弈)
题目链接:http://acm.zzuli.edu.cn/problem.php?id=2311
题目大意:刘备和孙权打炮台,每个炮台有a[i]滴血,一人一下(打的血量不限),最后打完的那人赢。刘备先打,问最后谁会赢)。
思路:异或和博弈。
ACCode:
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<map>
#include<set>
#include<deque>
#include<queue>
#include<stack>
#include<bitset>
#include<string>
#include<fstream>
#include<iostream>
#include<algorithm>
using namespace std;
#define ll long long
#define Pair pair<int,int>
//#define max(a,b) (a)>(b)?(a):(b)
//#define min(a,b) (a)<(b)?(a):(b)
#define clean(a,b) memset(a,b,sizeof(a))// ??
//std::ios::sync_with_stdio(false);
// register
const int MAXN=1e2+10;
const int INF32=0x3f3f3f3f;
const ll INF64=0x3f3f3f3f3f3f3f3f;
const ll mod=1e9+7;
const double PI=acos(-1.0);
const double EPS=1.0e-8;
int a[MAXN];
int main(){
int T;cin>>T;
while(T--){
int n;cin>>n;
for(int i=1;i<=n;++i) cin>>a[i];
int ans=0;
for(int i=1;i<=n;++i) ans^=a[i];
if(ans>0) cout<<"Liu_B is sure to win."<<endl;
else cout<<"Liu_B is not sure to win."<<endl;
}
}