2018.5.17我兴高采烈地来到了机房,本来以为昨天他们已经考完试了,我就不用考了,结果,是我多虑了。mxl老师让我自己做做,然后给我测一下。
然后,我拿到了题目,哦哟,居然!....不会。好吧,我已经习以为常了。
看到第一题,解方程哦,好简单啊,可我就是不会呢。真的是,一点思路都没有。
预计:0分 实际:0分
题解:用高斯消元求一下系数矩阵的逆矩阵,对于每次询问直接将其乘上逆矩阵即可
1 #include <cstdio> 2 #include <cstring> 3 #include <cmath> 4 #include <algorithm> 5 using namespace std; 6 const int maxn=110; 7 const int maxm=1010; 8 int n,m; 9 double A[maxn][maxn+maxm]; 10 double x[maxn]; 11 inline double pr(double x) { 12 if(fabs(x)<1e-9) return 0.000; 13 return x; 14 } 15 int main() { 16 freopen("equation.in","r",stdin); 17 freopen("equation.out","w",stdout); 18 scanf("%d%d",&n,&m); 19 for(int i=1; i<=n; i++) 20 for(int j=1; j<=n; j++) 21 scanf("%lf",A[i]+j); 22 for(int j=n+1; j<=n+m; j++) 23 for(int i=1; i<=n; i++) 24 scanf("%lf",A[i]+j); 25 for(int i=1; i<n; i++) { 26 int r=i; 27 for(int j=i+1; j<=n; j++) 28 if(fabs(A[r][i])<fabs(A[j][i])) r=j; 29 for(int j=i; j<=n+m; j++) swap(A[i][j],A[r][j]); 30 for(int j=i+1; j<=n; j++) { 31 if(A[j][i]==0) continue; 32 for(int k=i+1; k<=n+m; k++) A[j][k]-=A[i][k]/A[i][i]*A[j][i]; 33 A[j][i]=0; 34 } 35 } 36 for(int i=1; i<=m; i++) { 37 x[n]=A[n][n+i]/A[n][n]; 38 for(int j=n-1; j>0; j--) { 39 x[j]=A[j][n+i]; 40 for(int k=j+1; k<=n; k++) x[j]-=A[j][k]*x[k]; 41 x[j]/=A[j][j]; 42 } 43 printf("%.9f",pr(x[1])); 44 for(int j=2; j<=n; j++) printf(" %.9f",pr(x[j])); 45 puts(""); 46 } 47 return 0; 48 }
第二题,嗯。一开始是想到了很多的,但是奈于无法实现啊。然后,就想,如果m值不可分,是个奇数,那肯定是失败的,就输出“no”。还有,如果这个数一直分,一直除以2,如果次数还不如n,那也不行啊。(这是极端思想了,因为就算你是奇数,还可能有另一个数给你一半,你又变成偶数了)。
预计:40? 实际:70!
题解:
设d=gcd(a1,a2,...,an)可以证明若m=2^k*d则问题有解,否则问题无解。
令a1=b1*d,a2=b2*d,...,an=bn*d,找出所有bi为奇数的i,两两配对进行逆操作,如此所有的bi将变为偶数,d的值将会倍增,直到等于m为止。
倍增的次数为O(logm),配对的时间复杂度为O(n),故总时间复杂度O(nlogm)。
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; int a[10005]; int main() { freopen("divide.in","r",stdin); freopen("divide.out","w",stdout); int t; cin>>t; while(t--) { int n,m; cin>>n>>m; for(int i=1; i<=n; i++) { cin>>a[i]; } if(m%2==1||(n>2&&m/2%2==1)) { cout<<"no"<<"\n"; continue; } cout<<"yes"<<"\n"; } fclose(stdin); fclose(stdout); return 0; }
#include <cstdio> #include <cstring> int n,m,a[100010]; int p,u[1000010],v[1000010]; int gcd(int a,int b) { return b?gcd(b,a%b):a; } int main() { int t; freopen("divide.in","r",stdin); freopen("divide.out","w",stdout); scanf("%d",&t); while(t--) { scanf("%d%d",&n,&m); int d=0; for(int i=1; i<=n; i++) { scanf("%d",a+i); d=gcd(d,a[i]); } m/=d; for(int i=1; i<=n; i++) a[i]/=d; if((m&(-m))!=m) printf("no\n"); else { puts("yes"); p=0; for(int d=0; m>>d; d++) { int l=0; for(int i=1; i<=n; i++) if((a[i]>>d)&1) { if(!l) l=i; else { if(a[l]<=a[i]) { a[i]-=a[l], a[l]<<=1; u[++p]=l, v[p]=i; } else { a[l]-=a[i], a[i]<<=1; u[++p]=i, v[p]=l; } l=0; } } } /*printf("%d\n",p); for(int i=p;i>0;i--) printf("%d %d\n",u[i],v[i]);*/ } } return 0; }
不得不说,我们某位同学,随机数都得了70分,emmm。
第三题,嗯。。。很迷,我居然得了20分。
预计:0分 实际:20分!
题解:最大权闭合子图模型,使用最小割建图
1 #include<cstdio> 2 #include<algorithm> 3 using namespace std; 4 const int maxn = 500 + 10; 5 const int INF = 1<<29; 6 int x[maxn],y[maxn],r[maxn],ss[maxn]; 7 int tr[maxn],g[maxn][maxn]; 8 int n; 9 int tt; 10 inline int sqr( int x ) { 11 return x*x; 12 } 13 int q[maxn]; 14 int dis[maxn]; 15 bool BFS() { 16 for(int i=1; i<=tt; i++) dis[i] = INF; 17 dis[tt] = 0; 18 int l=0,r=1; 19 q[1] = tt; 20 int x; 21 while( l<r ) { 22 x = q[++l]; 23 tr[x] = 1; 24 for(int i=1; i<=tt; i++) if( dis[i]==INF && g[i][x] ) 25 dis[ q[++r] = i ] = dis[x] +1; 26 } 27 return dis[1]!=INF; 28 } 29 int dfs( int x,int nowd ) { 30 if( x==tt ) return nowd; 31 int z,cur = 0; 32 for( int &i = tr[x]; i<=tt; i++ ) if( g[x][i] && dis[i]==dis[x]-1 ) { 33 z = dfs(i,min(g[x][i],nowd)); 34 if(z) { 35 g[x][i]-=z; 36 g[i][x]+=z; 37 cur+=z; 38 nowd-=z; 39 if(nowd==0) break; 40 } 41 } 42 43 if(cur==0) dis[x] = INF; 44 return cur; 45 } 46 int main() { 47 freopen("wifi.in","r",stdin); 48 freopen("wifi.out","w",stdout); 49 int ans; 50 scanf("%d",&n); 51 tt = n+2; 52 for(int i=1; i<=tt; i++) 53 for(int j=1; j<=tt; j++) g[i][j] = 0; 54 for(int i=1; i<=n; i++) 55 scanf("%d%d%d%d",x+i,y+i,r+i,ss+i); 56 for(int i=1; i<=n; i++) if( ss[i]>=0 ) 57 g[1][i+1] = ss[i]; 58 else 59 g[i+1][tt] = -ss[i]; 60 for(int i=1; i<=n; i++) 61 for(int j=1; j<=n; j++) if(i!=j && sqr(x[i]-x[j])+sqr(y[i]-y[j]) <= sqr(r[i]) ) 62 g[i+1][j+1] = INF; 63 ans = 0; 64 for(int i=1; i<=n; i++) if(ss[i]>0) ans+=ss[i]; 65 while( BFS() ) ans-=dfs(1,INF); 66 printf("%d\n",ans); 67 return 0; 68 }
我们的cdx大佬说,这套题,第一道和第三道是省选以下难度,noip以上,第二题才是noip难度。emmmm。然后他觉得这套题很弱智,就只交了第二道题,还是第一,因为他A了。
而我们这种蒟蒻,哎。
一世安宁