DAY1
T1 生活大爆炸版 石头剪刀布
就直接模拟
#include<bits/stdc++.h>
using namespace std;
int n,na,nb,win_a,win_b;
int a[201],b[201];
bool jud[6][6];
void Judge(int x,int y){
if(x == y) return;
if(jud[x][y] == 1) win_a++;
else win_b++;
return;
}
int main()
{
// freopen("rps.in","r",stdin);
// freopen("rps.out","w",stdout);
jud[1][3]=jud[1][4]=jud[2][1]=jud[2][4]=jud[3][2]=1;
jud[3][5]=jud[4][3]=jud[4][5]=jud[5][1]=jud[5][2]=1;
scanf("%d %d %d ",&n,&na,&nb);
for(int i=1; i<=na; i++) scanf("%d",&a[i]),a[i]++;
for(int i=1; i<=nb; i++) scanf("%d",&b[i]),b[i]++;
int ia=0,ib=0;
while(n--){
ia = ia==na ? 1 : ia+1;
ib = ib==nb ? 1 : ib+1;
Judge(a[ia],b[ib]);
}
printf("%d %d",win_a,win_b);
return 0;
}
T2 联合权值
考场读题直接把图认为成了一条链,鸭蛋
正解:
- 思路:对于当前点i,联合权值即为i左右两边点的乘积!
- 第一问:最大值,即为i点两边的前2大点的乘积
- 第二问:总和,变形即为点值和的平方—各个点的平方!
AC码子
#include<bits/stdc++.h>
using namespace std;
#define N 200001
#define mod 10007
long long l,m,n;
long long kao[N];
vector <long long>ha[N];
int main(){
scanf("%lld",&n);
for(long long z=1; z<n; z++){
long long x,y;
scanf("%lld %lld",&x,&y);
ha[x].push_back(y);
ha[y].push_back(x);
}
for(long long z=1; z<=n; z++) scanf("%lld",&kao[z]);
for(long long z=1; z<=n; z++){
long long cal1=0,m1=0,m2=0;
for(long long y=0; y<ha[z].size(); y++){
long long x = ha[z][y];
cal1 += kao[x];
l -= kao[x]*kao[x];
if(kao[x]>m2){
if(kao[x]>m1){
m2 = m1;
m1 = kao[x];
}
else m2 = kao[x];
}
}
l += cal1*cal1; l %= mod;
m = max(m,m1*m2);
}
printf("%lld %lld",m,l);
return 0;
}
T3 飞扬的小鸟
70分,直接模拟+DP,注意无柱子均可以飞,到最高只能达到m
#include<bits/stdc++.h>
using namespace std;
#define N 10001
int n,m,k,sum;
int f[N][1001],dis[N][2],g[N][2];
bool Can_exist(int y,int i){
if(y > g[i][0]){
if(g[i][1] == 0)return true;
if(y < g[i][1]) return true;
}
return false;
}
int main()
{
// freopen("bird.in","r",stdin);
// freopen("bird.out","w",stdout);
scanf("%d %d %d",&n,&m,&k);
for(int i=0; i<=n-1; i++) scanf("%d %d",&dis[i][1],&dis[i][0]);
for(int i=1; i<=k; i++){
int t,x,y;
scanf("%d %d %d",&t,&x,&y);
g[t][0] = x;
g[t][1] = y;
}
memset(f,0x3f,sizeof(f));
for(int i=0; i<=m; i++) f[0][i] = 1;
for(int i=0; i<=n-1; i++){
bool find = false;
for(int j=0; j<=m; j++){
if(f[i][j]!=1061109567){
//down
int down = j - dis[i][0];
if(Can_exist(down,i+1)){
find = true;
f[i+1][down] = min(f[i+1][down],f[i][j]);
}
//up
int up=0;
for(int t=1; 1; t++){
up = j+t*dis[i][1];
if(Can_exist(up,i+1)){
find = true;
int up2 = up>m ? m : up;
f[i+1][up2] = min(f[i+1][up2],f[i][j]+t);
}else break;
if(up > m) break;
}
}
}
if(find == false){
int ans=0;
for(int j=1; j<=i; j++)
if(g[j][0] || g[j][1]) ans++;
printf("0\n%d",ans);
return 0;
}
}
int ans = 99999999;
for(int i=0; i<=m; i++) ans = min(ans,f[n][i]);
printf("1\n%d",ans-1);
return 0;
}
~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
DAY2
T1 无线网络发射器选址
直接枚举每个方形的中点,但是要注意四边范围,中点可以是棋盘任何位置!!!
(考试我没注意j的范围WA了3个点)
满分
#include<bits/stdc++.h>
using namespace std;
int d,n,maxn,sum;
int a[130][130],pre[130][130];
int main()
{
// freopen("wireless.in","r",stdin);
// freopen("wireless.out","w",stdout);
scanf("%d\n%d",&d,&n);
int x,y,z;
for(int i=1; i<=n; i++){
scanf("%d%d%d",&x,&y,&z);
pre[x][y] = a[x][y] = z;
}
for(int i=0; i<=128; i++)
for(int j=0; j<=128; j++)
pre[i][j] += pre[i][j-1];
for(int i=0; i<=128; i++)
for(int j=0; j<=128; j++){
int tot = 0;
int si = i-d>0?i-d:0, sj = j-d>0?j-d:0;
int ei = i+d<128?i+d:128,ej = j+d<128?j+d:128;
for(int i2=si; i2<=ei; i2++)
tot += (pre[i2][ej]-pre[i2][sj]+a[i2][sj]);
if(tot>maxn){
maxn = tot;
sum = 1;
}else if(tot == maxn) sum++;
}
printf("%d %d",sum,maxn);
return 0;
}
T2 寻找道路
考场暴力 10分
正解:
- 反向制表
- 从终点BFS,标记可以搜到的点,其他搜不到的后面则不选择作为路径
3. SPFA模板!!!
可爱的 代码
#include<bits/stdc++.h>
using namespace std;
int ct,s,t;
int used[300000],dis[300000],vis[300000],head[500000];
int n,m,x[300000],y[300000];
bool flag;
struct edge{
int next,to;
}e[500000];
void add(int from,int to){
e[++ct].to=to;
e[ct].next=head[from];
head[from]=ct;
return;
}
bool pd(int pos){
for(int i=head[pos];i;i=e[i].next)
if(!used[e[i].to]) return 0;
return true;
}
void BFS(){
queue<int>q;
q.push(t);used[t]=1;
while(!q.empty()){
int pos=q.front();q.pop();
for(int i=head[pos];i;i=e[i].next){
if(!used[e[i].to]){
q.push(e[i].to);
used[e[i].to]=1;
}
}
}
}
void SPFA()
{
queue<int> q;
q.push(s);dis[s]=0;vis[s]=1;
while(!q.empty()){
int p=q.front();vis[p]=0;q.pop();
if(pd(p)==0) continue;
for(int i=head[p];i;i=e[i].next){
int v=e[i].to;
if(dis[v]>dis[p]+1){
dis[v]=dis[p]+1;
if(!vis[v]){
q.push(v);
vis[v]=1;
}
if(v==t){ flag=true; }
}
}
}
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++){
scanf("%d%d",&x[i],&y[i]);
add(y[i],x[i]);
}
scanf("%d%d",&s,&t);
BFS();
if(!used[s]){//spj
printf("-1");
return 0;
}
memset(head,0,sizeof(head));
memset(dis,0x3f,sizeof(dis));
memset(vis,0,sizeof(vis));
ct=0;
for(int i=1;i<=m;i++)
add(x[i],y[i]);
SPFA();
if(flag==false) printf("-1");
else printf("%d",dis[t]);
return 0;
}
T3 解方程
考试的时候想到秦九韶(即不断提取公因式x,简化系数),但是不知道对an这么大的数怎么处理····
正解:咋处理an?让我们膜它! 可以发现:f(x)%质数==0则x是一个解!
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod=1e9+7;
template <typename _Tp> inline void read(_Tp &x){
char c11=getchar();x=0;bool booo=0;
while(c11<'0'||c11>'9'){if(c11=='-')booo=1;c11=getchar();}
while(c11>='0'&&c11<='9'){x=(x*10+c11-'0')%mod;c11=getchar();}
if(booo)x=-x;
return ;
}
const int maxn=101;
ll a[maxn];int st[1000005],p=0;
int n,m;
inline bool check(int x){
ll sum=0;
for(int i=n;i>-1;--i)
sum=((a[i]+sum)*x)%mod;//秦九韶!!!!!(即不断提公因式x)
return sum==0;
}
void work(){
for(int i=1;i<=m;++i)if(check(i))st[++p]=i;
check(65536);
printf("%d\n",p);for(int i=1;i<=p;i++)printf("%d\n",st[i]);
return ;
}
void init(){
read(n);read(m);
for(int i=0;i<=n;++i) read(a[i]);
}
int main(){
init();
work();
return 0;
}