G.Limit
分析:
这是一道实在的数学题,需要一定的高数思维和基础。
看到0<=t<=5就应该想到,分子应该可以等价替换成一个与x的指数有关的表达式。那应该是什么表达式呢?没错,就是泰勒公式展开式。
ln(1+x)=x-x^ 2/2+x ^3/3-x ^4/4+x ^5/5+…+(-1) ^(n-1)/n+…
想到这,这道题就已经没有难度了,只需要带进去看一下表达式就会发现接下来就是一道普通遍历的题了。
AC代码如下:
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;
int a[maxn],b[maxn],g[10];
int main(){
memset(g,0,sizeof(g));
int n,t;cin>>n>>t;
for(int i=1;i<=n;i++) cin>>a[i]>>b[i];
for(int i=1;i<=n;i++){
g[1]+=a[i]*b[i];
g[2]+=a[i]*b[i]*b[i]*(-1);
g[3]+=a[i]*b[i]*b[i]*b[i];
g[4]+=a[i]*b[i]*b[i]*b[i]*b[i]*(-1);
g[5]+=a[i]*b[i]*b[i]*b[i]*b[i]*b[i];
}
if(t==0) cout<<0<<endl;
else{
for(int i=1;i<t;i++){
if(g[i]!=0) {
cout<<"infinity"<<endl;
return 0;
}
}
cout<<g[t]/t<<endl;
}
return 0;
}
H.Set
分析:
由于最大的一个区间<=(512/r),那么我们可以使每一个区间的所包含的元素个数为maxx=512/r。把256个元素均分为k份,由于此时可能出现余数(也就是有些元素没有得到均分),所以需要对余数p单独处理,将他们平均分配给任意一个可能分到的区间,(分到的区间加一,其他不变)。最后就是用star充当起点去遍历他们。每次起点记得加每一份的所属那部分区间d=256/k。
AC代码如下:
#include<bits/stdc++.h>
using namespace std;
int main(){
int k,r,d,maxx,p;
cin>>k>>r;
d=256/k; maxx=512/r,p=256%k;
int star=1;
for(int i=1;i<=k;i++){
int cnt=maxx;
for(int j=1;j<=256;j++){
if((j>=star||256-star+j<=maxx)&&cnt){
cout<<1;
cnt--;
}
else cout<<0;
}
star+=d;
cout<<endl;
if(p) star++,p--;
}
return 0;
}
J.Leaking Roof
分析:
一道类似于广度优先搜索的题,我们只需要将所有的点按照高度从大到小排序,然后从大到小遍历一次,将他们的水流分散给周围所有高度比它小的区域即可。最后输出高度为0的区域的水量,高度不为0的输出0即可。
AC代码如下:
#include<bits/stdc++.h>
using namespace std;
int n,k,cnt=0,h[505][505];
int dx[6]={0,-1,1,0,0};
int dy[6]={0,0,0,-1,1};
double ans[505][505];
struct Node{
int x,y;
int h;
double m;
bool operator < (const Node &a){
return h>a.h;
}
}g[505*505];
inline int check(int x,int y){
if(x>=1&&x<=n&&y>=1&&y<=n) return 1;
return 0;
}
void bfs(int k){
int tot=0;
for(int i=1;i<=4;i++){
int tx=g[k].x+dx[i];
int ty=g[k].y+dy[i];
if(check(tx,ty)&&h[tx][ty]<g[k].h) tot++;
}
for(int i=1;i<=4;i++){
int tx=g[k].x+dx[i];
int ty=g[k].y+dy[i];
if(check(tx,ty)&&h[tx][ty]<g[k].h){
ans[tx][ty]+=ans[g[k].x][g[k].y]/tot;
}
}
}
void solve(){
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++){
cin>>h[i][j];
g[++cnt].x=i;g[cnt].y=j;
g[cnt].m+=k;
ans[i][j]+=k;g[cnt].h=h[i][j];
}
sort(g+1,g+1+cnt);
for(int i=1;i<=cnt;i++){
bfs(i);
}
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
if(h[i][j]!=0) cout<<0<<" ";
else printf("%.6lf ",ans[i][j]);
}
cout<<endl;
}
}
int main(){
cin>>n>>k;
solve();
return 0;
}
L.Euler Function
M.Addition
分析:
本题的难点在于进位的处理。一道签到题,却卡了好久,太菜了,qaq。
二进制数据从小到大相加时,由于进位多变化,可正可负数,还可为0;那么就需要统一处理了。将进位数jin乘上sgn[i],是为了让va[i]+vb[i]+jin的时候可以做到同号相加,异号相减。接下来就是分类讨论的过程,需要读者仔细思索了。
AC代码如下:
#include<bits/stdc++.h>
using namespace std;
int main(){
int n,sgn[100],va[100],vc[100],vb[100];cin>>n;
for(int i=0;i<n;i++) cin>>sgn[i];
for(int i=0;i<n;i++) cin>>va[i];
for(int i=0;i<n;i++) cin>>vb[i];
int jin=0;
for(int i=0;i<n;i++){
jin*=sgn[i];
int temp=va[i]+vb[i]+jin;
if(temp==0||temp==1) vc[i]=temp,jin=0;
else if(temp==-1) vc[i]=1,jin=-1;
else if(temp==2) vc[i]=0,jin=1;
else if(temp==3) vc[i]=1,jin=1;
jin*=sgn[i];
}
for(int i=0;i<n-1;i++) cout<<vc[i]<<" ";
cout<<vc[n-1];
return 0;
}
/*
32
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
*/