codeforces#341
A题:偶数直接加进去,奇数排序后去掉最小的即可。
/* ID: NotPassedCET4 PROG: #341 LANG: C++ */ #include<bits/stdc++.h> #define REP(i,a,b) for(int i=a;i<=b;i++) #define MS0(a) memset(a,0,sizeof(a)) using namespace std; typedef long long ll; const int maxn=1000100; const int INF=1e9+10; ll o[maxn],on,e[maxn],en; int n; int main() { freopen("in.txt","r",stdin); while(cin>>n){ on=en=0; REP(i,1,n){ ll x;scanf("%I64d",&x); if(x&1) o[++on]=x; else e[++en]=x; } ll s=0; sort(o+1,o+on+1); REP(i,1,en) s+=e[i]; int k=1; if(on&1) k=2; for(int i=on;i>=k;i--) s+=o[i]; cout<<s<<endl; } return 0; }
B题:由于主对角线和辅对角线对结果的影响是独立,所以分开找即可,对每个对角线内的k个棋子,对答案的贡献是C(k,2)。
/* ID: NotPassedCET4 PROG: #341 LANG: C++ */ #include<bits/stdc++.h> #define REP(i,a,b) for(int i=a;i<=b;i++) #define MS0(a) memset(a,0,sizeof(a)) using namespace std; typedef long long ll; const int maxn=1000100; const int INF=1e9+10; int n; struct Node { int x,y; int z,w; };Node p[maxn]; bool cmpz(Node A,Node B) { return A.z<B.z; } bool cmpw(Node A,Node B) { return A.w<B.w; } int main() { freopen("in.txt","r",stdin); while(cin>>n){ REP(i,1,n) scanf("%d%d",&p[i].x,&p[i].y); REP(i,1,n){ p[i].z=p[i].x+p[i].y-1; p[i].w=p[i].x-p[i].y; } sort(p+1,p+n+1,cmpz); ll ans=0; for(int i=1;i<=n;){ int j=i; while(j<=n&&p[j].z==p[i].z) j++; ll cnt=j-i; ans+=cnt*(cnt-1)/2; i=j; } sort(p+1,p+n+1,cmpw); for(int i=1;i<=n;){ int j=i; while(j<=n&&p[j].w==p[i].w) j++; ll cnt=j-i; ans+=cnt*(cnt-1)/2; i=j; } cout<<ans<<endl; } return 0; }
C题:对每个个体单独计算对答案的贡献期望即可,算是数学题吧。。写的时候碰到两个问题,一是算边界的时候用了二分,其实直接前缀和f(r)-f(l-1)即可,其中f(x)=x/p;另外一个是式子没写清楚,分母写错了。。
/* ID: NotPassedCET4 PROG: #341 LANG: C++ */ #include<bits/stdc++.h> #define REP(i,a,b) for(int i=a;i<=b;i++) #define MS0(a) memset(a,0,sizeof(a)) using namespace std; typedef long long ll; const int maxn=1000100; const int INF=1e9+10; int n;ll pt; struct Node { ll l,r; ll len; ll x,y; void read() { scanf("%I64d%I64d",&l,&r); len=r-l+1; x=r/pt-(l-1)/pt; y=len-x; } };Node p[maxn]; int main() { freopen("in.txt","r",stdin); while(cin>>n>>pt){ REP(i,1,n){ p[i].read(); } double ans=0; REP(i,1,n){ int j=i-1,k=i+1; if(j==0) j=n; if(k==n+1) k=1; double tmp=0; tmp+=(1.0*p[j].len*p[i].x*p[k].len+1.0*p[j].x*p[i].y*p[k].x)*2000; tmp+=(1.0*p[j].y*p[i].y*p[k].x+1.0*p[j].x*p[i].y*p[k].y)*1000; tmp/=1.0*p[j].len*p[i].len*p[k].len; ans+=tmp; } printf("%.8f\n",ans); } return 0; }
D题:这是个无聊的水题。。去一下对数用long double然后排序一下就行了,这里注意取一阶对数,另外一阶直接用pow。。
/* ID: NotPassedCET4 PROG: #341 LANG: C++ */ #include<bits/stdc++.h> #define REP(i,a,b) for(int i=a;i<=b;i++) #define MS0(a) memset(a,0,sizeof(a)) using namespace std; typedef long long ll; const int maxn=1000100; const int INF=1e9+10; const double EPS=1e-10; long double x,y,z; long double f1(long double x,long double y,long double z) { return pow(y,z)*log(x); } long double f2(long double x,long double y,long double z) { return y*z*log(x); } struct Node { long double v; int id; friend bool operator<(Node A,Node B) { if(A.v>B.v+EPS) return 1; if(fabs(A.v-B.v)<EPS) return A.id<B.id; return 0; } };Node a[20];int n; const string s[14]= { "","x^y^z","x^z^y","(x^y)^z","(x^z)^y", "y^x^z","y^z^x","(y^x)^z","(y^z)^x", "z^x^y","z^y^x","(z^x)^y","(z^y)^x", }; int main() { freopen("in.txt","r",stdin); while(cin>>x>>y>>z){ n=12; REP(i,1,n) a[i].id=i; a[1].v=f1(x,y,z); a[2].v=f1(x,z,y); a[3].v=f2(x,y,z); a[4].v=f2(x,z,y); a[5].v=f1(y,x,z); a[6].v=f1(y,z,x); a[7].v=f2(y,x,z); a[8].v=f2(y,z,x); a[9].v=f1(z,x,y); a[10].v=f1(z,y,x); a[11].v=f2(z,x,y); a[12].v=f2(z,y,x); sort(a+1,a+n+1); if(a[1].id==4||a[1].id==8||a[1].id==12) a[1].id--; cout<<s[a[1].id]<<endl; } return 0; }
E题:很容易写出dp方程,前i位余数为j的方案数为 dp[i][j]=dp[i-1][k]*cnt[t],其中j=(k*10+t)%x,i范围最大可到1e9,因此只有快速幂了。
先解出t=(j-10*k)%x;
那么为了方便快速幂,方程简化一下:f[i]=f[j]*cnt[(i-10*j)%x]。(0<=i<x)
f[i]为当前项,f[j]为前一项,显然转移矩阵为A[i][j]=cnt[(i-10*j)%x],这样问题就解决了。
大概如下。。。
| f[0] | | A[0][0] A[0][1].... A[0][x-1] | | f[0] |
| f[1] | = | | | f[1] |
| . | | | * | . |
| . | | | | . |
| f[x-1] | |A[x-1][0] ............ A[x-1][x-1] | | f[x-1] |
/* ID: NotPassedCET4 PROG: #341 LANG: C++ */ #include<bits/stdc++.h> #define REP(i,a,b) for(int i=a;i<=b;i++) #define MS0(a) memset(a,0,sizeof(a)) using namespace std; typedef long long ll; const int maxn=1000100; const int INF=1e9+10; const ll p=1e9+7; const int N=102; ll n,b,k,x; struct Matrix { ll a[N][N]; friend Matrix operator*(Matrix A,Matrix B) { Matrix res={}; REP(i,0,x-1){ REP(j,0,x-1){ REP(k,0,x-1){ res.a[i][j]=(res.a[i][j]+((A.a[i][k]%p)*(B.a[k][j]%p))%p)%p; } } } return res; } }; ll cnt[N]; ll Fs[N],Ft[N]; Matrix qpow(Matrix n,ll k) { Matrix res={}; REP(i,0,x-1) res.a[i][i]=1; while(k){ if(k&1) res=res*n; n=n*n; k>>=1; } return res; } int main() { freopen("in.txt","r",stdin); while(cin>>n>>b>>k>>x){ MS0(cnt); REP(i,1,n){ int y;scanf("%d",&y); cnt[y%x]++; } REP(i,0,x-1) Fs[i]=cnt[i],Ft[i]=0; Matrix A; REP(i,0,x-1){ REP(j,0,x-1){ A.a[i][j]=cnt[(i+10*x-10*j)%x]; } } A=qpow(A,b-1); REP(i,0,x-1){ REP(j,0,x-1){ Ft[i]=(((Fs[j]%p)*(A.a[i][j]%p))%p+Ft[i]%p)%p; } } cout<<Ft[k]<<endl; } return 0; }
总结,代码速度和准确性并不算太差,但是用在分析的时间较少,对题目没有充分的分析和判断就直接写了,这导致比赛中常常选择不合理的思路。不过已经慢慢找回状态了。