A:gpa
分数规划裸题了吧,然后二分次数过多的话会超时
#include<cstdio> #include<cstdlib> #include<cstring> #include<algorithm> using namespace std; const int MAX=1e5+5; int n,k; double s[MAX],c[MAX]; double tmp[MAX]; int check(double x){ int i; double ans=0; for(i=0;i<n;i++) tmp[i]=s[i]*c[i]-x*s[i]; sort(tmp,tmp+n); for(i=n-1;i>=k;i--) ans+=tmp[i]; if(ans>0) return 1; return 0; } double bsearch(double left,double right){ int i; double mid; for(i=0;i<60;i++){ mid=(left+right)/2; if(check(mid)) left=mid; else right=mid; } return mid; } int main(){ int i; scanf("%d%d",&n,&k); for(i=0;i<n;i++) scanf("%lf",&s[i]); for(i=0;i<n;i++) scanf("%lf",&c[i]); double ans=bsearch(0,1e9); printf("%.7lf\n",ans); return 0; }
B: div
主要是结论比较难构造出来,当然如果oeis技巧足够强,这就是小事。推出结论就很简单了,java大数随便写写就好了
附结论证明
import java.math.BigInteger; import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner cin = new Scanner(System.in); BigInteger m=cin.nextBigInteger(); BigInteger a1 =new BigInteger("0"); BigInteger a2 =new BigInteger("2"); BigInteger b1 =new BigInteger("0"); BigInteger b2 =new BigInteger("6"); BigInteger a3,b3; BigInteger k1 =new BigInteger("6"); BigInteger k2 =new BigInteger("14"); while(a2.compareTo(m)<=0) { a3=a2.multiply(k1).subtract(a1); a1=a2; a2=a3; } while(b2.compareTo(m)<=0) { b3=b2.multiply(k2).subtract(b1); b1=b2; b2=b3; } System.out.println(a2.min(b2)); } }
D: inv
E:room
二分图最大权值匹配,将旧安排和新安排两两之间建边,容量为1,权值为这两个房间相同人的数量。因为凡是前后不在同一个宿舍的人可以只通过一次就交换到新宿舍,所以只要不交换的人尽量多即可
#include <cstdio> #include <cstring> #include <queue> #include <algorithm> #include <cmath> #include <vector> #include <stack> #include <set> using namespace std; const int INF=0x3f3f3f3f; const int MAX=1e3+5; const int ext=200; struct node{ int v,f,cost,next; }edge[MAX*MAX]; int no,s,t; int head[MAX],dis[MAX],vis[MAX],pre[MAX],rec[MAX]; //pre记录前驱 rec记录边在edge中编号 queue<int> q; void init(void){ no=0; memset(head,-1,sizeof head); } void addedge(int u,int v,int f,int cost){ edge[no].v=v; edge[no].f=f; edge[no].cost=cost; edge[no].next=head[u]; head[u]=no++; edge[no].v=u; edge[no].f=0; edge[no].cost=-cost; edge[no].next=head[v]; head[v]=no++; } int spfa(int s,int t){ int k,tp; memset(dis,0x3f,sizeof(dis)); memset(vis,0,sizeof(vis)); while(!q.empty()) q.pop(); q.push(s); dis[s]=0; vis[s]=1; while(!q.empty()){ tp=q.front(); q.pop(); vis[tp]=0; for(k=head[tp];k!=-1;k=edge[k].next) if(dis[edge[k].v]>dis[tp]+edge[k].cost&&edge[k].f){ dis[edge[k].v]=dis[tp]+edge[k].cost; pre[edge[k].v]=tp; rec[edge[k].v]=k; if(vis[edge[k].v]==0){ vis[edge[k].v]=1; q.push(edge[k].v); } } } if(dis[t]==INF) return 0; return 1; } pair<int, int> Mcmf(int s,int t){ int minflow,k,mincost=0,maxflow=0; while(spfa(s,t)){ k=t; minflow=INF; while(k!=s){ minflow=min(minflow,edge[rec[k]].f); k=pre[k]; } k=t; maxflow+=minflow; while(k!=s){ mincost+=minflow*edge[rec[k]].cost; edge[rec[k]].f-=minflow; edge[rec[k]^1].f+=minflow; k=pre[k]; } } return make_pair(maxflow,mincost); } int n; int x[MAX][10],y[MAX][10]; int main(){ int i,j,k,p; init(); scanf("%d",&n); for(i=1;i<=n;i++) for(j=0;j<4;j++) scanf("%d",&x[i][j]); for(i=1;i<=n;i++){ for(j=0;j<4;j++) scanf("%d",&y[i][j]); for(j=1;j<=n;j++){ int cnt=0; for(k=0;k<4;k++) for(p=0;p<4;p++) if(y[i][k]==x[j][p]) cnt++; addedge(j,i+ext,1,4-cnt); } } int s=0,t=200+ext; for(i=1;i<=n;i++){ addedge(s,i,1,0); addedge(i+ext,t,1,0); } pair<int,int> ans=Mcmf(s,t); printf("%d\n",ans.second); return 0; }
F: take
G:max
取[1,n/c]中的最大两个就行,然后特别讨论一下n/c=1情况
#include <cstdio> #include <cstring> #include <queue> #include <algorithm> #include <cmath> #include <vector> #include <iostream> #include <stack> #include <set> #include <map> #define LSON l,m,x<<1 #define RSON m+1,r,x<<1|1 using namespace std; long long c,n; int main(){ scanf("%lld%lld",&c,&n); long long x=n/c; if(x<1){ puts("-1"); return 0; } if(x==1){ printf("%lld\n",c*c); return 0; } long long ans=x*(x-1); printf("%lld\n",ans*c*c); return 0; }
H:subseq
I:vcd
J:plan
待填
#include<cstdio> #include<cstdlib> #include<cstring> #include<algorithm> using namespace std; typedef long long LL; long long n,p1,p2; long long ans; int main(){ scanf("%lld%lld%lld",&n,&p1,&p2); LL tmp1,tmp2; tmp1=(n/2)*p1; tmp2=(n/3)*p2; if(n%2==1){ LL tmp; tmp=min(p1,p2); if(tmp1) tmp=min(tmp,-p1+p2); tmp1+=tmp; } if(n%3==1){ LL tmp; tmp=min(p1,p2); if(tmp2) tmp=min(tmp,-p2+p1+p1); tmp2+=tmp; } else if(n%3==2){ LL tmp; tmp=min(p1,p2); tmp2+=tmp; } printf("%lld",min(tmp1,tmp2)); return 0; }