D. 题目要找如题目所示的那种菱形的个数
只要DFS两层,看每个点走两步都可以到哪些点,记录下来,最后就是组合数统计一下和就行了。
#include <stdio.h> #include <string.h> #include <algorithm> #include <vector> using namespace std; vector<int> edge[3005]; int ans[3005][3005]; void dfs(int t,int s,int step) { int i; if (step==2) { ans[s][t]++; return; } for (i=0;i<edge[t].size();i++) { dfs(edge[t][i],s,step+1); } } int main() { int i,j,n,m,x,y; scanf("%d%d",&n,&m); for (i=0;i<m;i++) { scanf("%d%d",&x,&y); edge[x].push_back(y); } for (i=1;i<=n;i++) { dfs(i,i,0); } long long s=0; for (i=1;i<=n;i++) { for (j=1;j<=n;j++) { if (i==j) continue; s+=(ans[i][j]*(ans[i][j]-1))/2; } } printf("%I64d\n",s); return 0; }
题目要求的是(d1+d2+d3+....)/(b1+b2+b3+....)的比例最小,假设(d1+d2+...)/(b1+b2+b3+...)的最小值为r,则有(d1+d2+...)/(b1+b2+...)>=r
整理一下得到(d1-b1*r)+(d2-b2*r)+...>=0
所以可以二分r,然后O(n^2)计算左边部分的最小值,看是否大于0,如果大于0,则扩大r,否则缩小r。
代码
#include <stdio.h> #include <math.h> #include <string.h> #include <algorithm> using namespace std; #define eps 1e-9 int x[1005]; int b[1005]; double dp[1005]; int before[1005]; int n,l; bool checkValid(double r) { int i,j; for (i=0;i<=n;i++) dp[i]=1e12; dp[0]=0; for (i=1;i<=n;i++) { for (j=0;j<i;j++) { double tmp=dp[j]+sqrt(abs(l-(x[i]-x[j]))*1.0)-r*b[i]; if (tmp<dp[i]) { dp[i]=tmp; before[i]=j; } } } return dp[n]>0; } void printAns(int t) { if (t==0) return; printAns(before[t]); printf("%d",t); if (t<n) printf(" "); } int main() { int i,j; scanf("%d%d",&n,&l); x[0]=b[0]=0; for (i=1;i<=n;i++) { scanf("%d%d",&x[i],&b[i]); } double l=0,r=1e7; while((r-l)>eps) { double mid=(l+r)/2; if (checkValid(mid)) l=mid; else r=mid; } printAns(n); return 0; }
代码
#include <stdio.h> #include <string.h> #include <algorithm> using namespace std; char str[1000]; int init[1000]; long long dp[505][505]; int main() { int i,j,n,m,mod; scanf("%d%d%d",&n,&m,&mod); memset(init,0,sizeof(init)); for (i=0;i<m;i++) { scanf("%s",str); for (j=0;j<n;j++) { if (str[j]=='1') init[j]++; } } int zero=0,one=0; for (i=0;i<n;i++) { if (init[i]==0) zero++; else if (init[i]==1) one++; } memset(dp,0,sizeof(dp)); dp[zero][one]=1; for (i=zero;i>=0;i--) { for (j=n;j>=0;j--) { if (i>=2) dp[i-2][j+2]+=(long long)i*(i-1)/2*dp[i][j]%mod; if (i>=1 && j>=1) dp[i-1][j]+=(long long)i*j*dp[i][j]%mod; if (j>=2) dp[i][j-2]+=(long long)j*(j-1)/2*dp[i][j]%mod; } } printf("%I64d\n",dp[0][0]); return 0; }