DAY1
生活大爆炸版石头剪刀布
直接模拟即可。
// codevs3716 #include<algorithm> #include<iostream> #include<cstdlib> #include<cstring> #include<cstdio> #include<cmath> #define LL long long #define MOD 1000000007 #define inf 2147483640 #define Pi acos(-1.0) #define free(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout); using namespace std; const int maxn=2000; int c[5][5]={{0,0,1,1,0}, {1,0,0,1,0}, {0,1,0,0,1}, {0,0,1,0,1}, {1,1,0,0,0}}; int a[maxn],b[maxn]; int main() { int n,na,nb; scanf("%d%d%d",&n,&na,&nb); for (int i=0;i<na;i++) scanf("%d",&a[i]); for (int i=0;i<nb;i++) scanf("%d",&b[i]); int A=0,B=0; for (int i=0;i<n;i++) { A+=c[a[i%na]][b[i%nb]]; B+=c[b[i%nb]][a[i%na]]; } printf("%d %d",A,B); return 0; }
联合权值
一开始无脑枚举,因为只需要dfs1层,感觉完全不虚,结果被菊花树卡得只有70分,于是怒水一发树形dp。
// codevs3728 #include<algorithm> #include<iostream> #include<cstdlib> #include<cstring> #include<cstdio> #include<cmath> #define LL long long #define MOD 10007 #define inf 2147483640 #define Pi acos(-1.0) #define free(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout); using namespace std; const int maxn=200010; struct edge {int to,next;}e[maxn<<1]; int head[maxn],n,cnt,w[maxn],ans1,ans2;; void link(int u,int v) { e[++cnt].to=v;e[cnt].next=head[u];head[u]=cnt; e[++cnt].to=u;e[cnt].next=head[v];head[v]=cnt; } void dfs(int x,int fa,int f) { ans1=(ans1+w[x]*w[f]);ans2=max(ans2,w[x]*w[f]); int x1=0,x2=0; for (int i=head[x];i;i=e[i].next) if (e[i].to!=fa) { dfs(e[i].to,x,fa); ans2=max(ans2,x2*w[e[i].to]); ans1=(ans1+x1*w[e[i].to])%MOD; x1=(x1+w[e[i].to])%MOD;x2=max(x2,w[e[i].to]); } } int main() { scanf("%d",&n); for (int u,v,i=1;i<n;i++) { scanf("%d%d",&u,&v); link(u,v); } for (int i=1;i<=n;i++) scanf("%d",&w[i]); dfs(1,0,0); printf("%d %d",ans2,ans1*2%MOD); return 0; }
飞扬的小鸟
一开始打了个nm²加队列乱搞可以获得85分的高分哦!正解背包。
// codevs3729 #include<algorithm> #include<iostream> #include<cstdlib> #include<cstring> #include<cstdio> #include<cmath> #define LL long long #define inf 100000000 #define Pi acos(-1.0) #define free(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout); using namespace std; const int maxn=10010,maxm=1010; struct data {int p,l,r;}t[maxn]; int n,m,K,u[maxn],d[maxn],l[maxn],r[maxn],f[maxn][maxm]; int main() { scanf("%d%d%d",&n,&m,&K); for (int i=0;i<n;i++) scanf("%d%d",&u[i],&d[i]); for (int i=0;i<=n;i++) l[i]=0,r[i]=m+1; for (int x,i=1;i<=K;i++) { scanf("%d",&x); scanf("%d%d",&l[x],&r[x]); } int cnt=0; for (int i=1;i<=n;i++) { for (int j=1;j<=m;j++) { f[i][j]=inf; if (j>u[i-1]) f[i][j]=min(f[i][j],min(f[i-1][j-u[i-1]],f[i][j-u[i-1]])+1); } for (int j=m-u[i-1];j<=m;j++) f[i][m]=min(f[i][m],min(f[i-1][j],f[i][j])+1); for (int j=l[i]+1;j<=r[i]-1;j++) if (j+d[i-1]<=m) f[i][j]=min(f[i][j],f[i-1][j+d[i-1]]); for (int j=1;j<=l[i];j++) f[i][j]=inf; for (int j=r[i];j<=m;j++) f[i][j]=inf; int flag=0; for (int j=1;j<=m;j++) if (f[i][j]<inf) {flag=1;break;} if (!flag) {printf("0 %d",cnt);return 0;} else if (r[i]!=m+1) cnt++; } int ans=inf; for (int i=1;i<=m;i++) ans=min(ans,f[n][i]); printf("1 %d",ans); return 0; }
DAY2
无线网络发射选址
无脑枚举。
// codevs3730 #include<algorithm> #include<iostream> #include<cstdlib> #include<cstring> #include<cstdio> #include<cmath> #include<queue> #define LL long long #define MOD 10007 #define inf 2147483640 #define Pi acos(-1.0) #define free(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout); using namespace std; int f[200][200],n,d; int main() { scanf("%d%d",&d,&n); for (int x,y,k,i=1;i<=n;i++) { scanf("%d%d%d",&x,&y,&k); f[x][y]=k; } int ans=0,tot=0; for (int i=0;i<=128;i++) for (int j=0;j<=128;j++) { int cnt=0; for (int k=max(i-d,0);k<=min(i+d,128);k++) for (int l=max(j-d,0);l<=min(j+d,128);l++) cnt+=f[k][l]; if (ans==cnt) tot++; else if (ans<cnt) ans=cnt,tot=1; } printf("%d %d",tot,ans); return 0; }
寻找道路
写得奇丑无比。。还Wa了两发,数组开小了→_→。。先反向连边处理哪些点能走哪些点不能走,然后Dijkstra。
// codevs3731 #include<algorithm> #include<iostream> #include<cstdlib> #include<cstring> #include<cstdio> #include<cmath> #include<queue> #define LL long long #define MOD 10007 #define inf 2147483640 #define Pi acos(-1.0) #define free(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout); using namespace std; const int maxn=10010,maxm=200010; struct edge {int to,next;}e[maxm<<1]; struct data { int num,w; friend bool operator < (const data a,const data b) { return a.w>b.w; } }; int head[maxn],f[maxn],vis[maxn],dis[maxn],u[maxm],v[maxm]; int n,m,cnt,s,t; void link(int u,int v) { e[++cnt].to=v;e[cnt].next=head[u];head[u]=cnt; } void dfs(int x) { vis[x]=1; for (int i=head[x];i;i=e[i].next) if (!vis[e[i].to]) dfs(e[i].to); } void Dijkstra() { priority_queue<data> q; data x=(data){s,0},y; for (int i=1;i<=n;i++) dis[i]=inf,vis[i]=0; dis[s]=0;q.push(x); while (!q.empty() && !vis[t]) { x=q.top();q.pop(); if (vis[x.num]) continue; vis[x.num]=1; for (int i=head[x.num];i;i=e[i].next) if (f[e[i].to] && dis[e[i].to]>x.w+1) { dis[e[i].to]=y.w=x.w+1; y.num=e[i].to; q.push(y); } } } int main() { scanf("%d%d",&n,&m); for (int i=1;i<=m;i++) { scanf("%d%d",&u[i],&v[i]); link(v[i],u[i]); //link(u,v); } scanf("%d%d",&s,&t);swap(s,t); dfs(s); memset(head,0,sizeof(head));cnt=0; for (int i=1;i<=m;i++) link(u[i],v[i]); for (int i=1;i<=n;i++) { f[i]=vis[i]; for (int j=head[i];j;j=e[j].next) f[i]&=vis[e[j].to]; } swap(s,t); Dijkstra(); printf("%d",dis[t]==inf ? -1 : dis[t]); return 0; }
解方程
一开始一直纠结怎么优化高精度,一直无果。。模了题解没想到是这这样的结果→_→。
我们发现若将等式左侧模上一个数等于0,那么有可能这个x是解。而在模M的意义下,f[x]与f[x+M]的值是一样的。于是我们就随便搞5个素数,分别预处理出从1~M-1的范围中的解,然后枚举x判断即可。
// codevs3732 #include<algorithm> #include<iostream> #include<cstdlib> #include<cstring> #include<cstdio> #include<cmath> #include<queue> #define LL long long #define MOD 10007 #define inf 2147483640 #define Pi acos(-1.0) #define free(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout); using namespace std; const int maxn=1000010; int M[5]={9973,9931,9941,9949,9967}; int ans[maxn],a[5][maxn],res[5][maxn],pre[5][maxn]; int n,m; int cal(int t,int x) { int sum=0; for (int i=0;i<=n;i++) sum=(sum+a[t][i]*pre[t][i])%M[t]; if (sum<0) sum+=M[t]; return sum; } bool check(int x) { for (int t=0;t<5;t++) if (res[t][x%M[t]]!=0) return 0; return 1; } int main() { scanf("%d%d",&n,&m); char ch[10010]; for (int i=0;i<=n;i++) { scanf("%s",ch+1); int l=strlen(ch+1); bool flag=0; for (int t=0;t<5;t++) { if (ch[1]!='-') a[t][i]=ch[1]-'0'; else a[t][i]=0,flag=1; } for (int t=0;t<5;t++) { for (int k=2;k<=l;k++) a[t][i]=(a[t][i]*10+ch[k]-'0')%M[t]; if (flag) a[t][i]=-a[t][i]; } } for (int t=0;t<5;t++) for (int x=1;x<M[t];x++) { pre[t][0]=1; for (int i=1;i<=n;i++) pre[t][i]=(pre[t][i-1]*x)%M[t]; res[t][x]=cal(t,x); } for (int i=1;i<=m;i++) if (check(i)) ans[++ans[0]]=i; printf("%d ",ans[0]); for (int i=1;i<=ans[0];i++) printf("%d ",ans[i]); return 0; }