A:多推几组样例可以发现合法的情况下,答案就是a/k+b/k,由于打的比赛场数
是完整的,所以不存在的条件就是a%k=0并且b不等于0或者b%k=0并且a不等于0
B:以图片上的字母对称,注意题上的i是对称的。
C:
方法一:前缀和加上二分,因为是整数,前缀和满足递增。由于查询的值
<=5000,记忆化一下答案就可以了。二分的过程中,当二分到的和大于5000可以
剪枝。
方法二:利用two pointer O(n)解决。也要记忆化答案来优化。这个题只要记忆化
答案就放过了。下面这份代码跑了1996ms。
#include <bits/stdc++.h>
using namespace std;
const int maxn = 100010;
int ans[5010],a[maxn];
int n, q, x;
int main()
{
while(~scanf("%d%d",&n,&q))
{
for(int i=1; i<=n; i++) scanf("%d", &a[i]);
memset(ans,-1,sizeof(ans));
while(q--){
scanf("%d", &x);
if(ans[x]!=-1){
printf("%d\n", ans[x]);
}
else{
int r=1,sum=0,anss=0;
for(int l=1; l<=n; l++){
while(r<=n&&sum+a[r]<=x){
sum+=a[r];
r++;
}
anss=max(anss,sum);
sum-=a[l];
}
printf("%d\n", anss);
ans[x]=anss;
}
}
}
return 0;
}
D:DFS,显然已经损坏的木板是不能走的,那么假如能够不经过损坏的木板走到
终点并且终点这块木板是损坏的,那么就是有解的,相反就是无解。
#include<bits/stdc++.h>
using namespace std;
int n, m, r1, c1, r2, c2;
char mat[35][35];
bool vis[35][35];
bool test = false;
bool valid(int a, int b)
{
if(a == r2 && b == c2)return true;
return !(a < 1 || b < 1 || a > n || b > m || mat[a][b] == 'X');
}
void dfs(int i, int j)
{
if(!valid(i, j))
return;
if(i == r2 && j == c2 && mat[i][j] == 'X')
{
test = true;
}
mat[i][j] = 'X';
dfs(i + 1, j);
dfs(i - 1, j);
dfs(i, j + 1);
dfs(i, j - 1);
}
int main()
{
while(scanf("%d%d", &n, &m) != EOF)
{
test = false;
memset(vis, false, sizeof vis);
for(int i = 1; i <= n; i++)
{
for(int j = 1; j <= m; j++)
{
cin >> mat[i][j];
}
}
cin >> r1 >> c1 >> r2 >> c2;
mat[r1][c1] = '.';
dfs(r1, c1);
cout << (test ? "YES" : "NO")<<endl;
}
return 0;
}
E:模拟题,注意后导0,然后像高精度那样模拟即可。
#include <bits/stdc++.h>
using namespace std;
char s[505];
string ans1,ans2;
int main()
{
while(cin>>s)
{
int len=strlen(s);
int pos;
int xx=0,flag=0;
for(int i=0; i<len; i++)
{
if(s[i]=='.') pos=i;
else if(s[i]=='e') flag=1;
else if(flag&&isdigit(s[i])) xx=(xx*10+s[i]-'0');
}
pos=pos+xx;
ans1="";
ans2="";
for(int i=0; i<len; i++)
{
if(s[i]=='.') continue;
if(s[i]=='e') break;
ans1+=s[i];
}
int curlen=ans1.size();
for(int i=curlen; i<500; i++) ans1+='0';
for(int i=0; i<pos; i++) ans2+=ans1[i];
ans2+='.';
for(int i=pos; i<500; i++) ans2+=ans1[i];
int le=(int)ans2.size();
while(ans2[--le]=='0');
if(ans2[le]=='.') le--;
ans2[le+1]='\0';
for(int i=0; i<le+1; i++) cout<<ans2[i];
cout<<endl;
}
return 0;
}
F:概率DP。用dp[x][y]记录当前还剩x张白卡,y张红卡卡牧师获胜的概率。考虑
这个DP的转移,牧师可以直接摸到白卡,如果红卡小于两张,但前面保证有卡,
所以红卡被牧师抽到,术士抽到白卡,赢的概率为0,所以让牧师先抽一张红卡,
然后术士再抽一张红卡,分别计算概率,然后用这个概率乘上后面转移到的状态即
可。
#include<bits/stdc++.h>
using namespace std;
const int maxn=1005;
double dp[maxn][maxn];
int vis[maxn][maxn];
double dfs(int x,int y)
{
if(x<=0) return 0;
if(y<=0) return 1;
if(vis[x][y]) return dp[x][y];
vis[x][y]=1;
double ans=1.0*x/(x+y);
if(y>=2)
{
double k=1.0*y/(x+y);
y--;
k*=1.0*y/(x+y);
y--;
dp[x-1][y]=dfs(x-1,y);
dp[x][y-1]=dfs(x,y-1);
ans+=k*(1.0*x/(x+y)*dp[x-1][y]+1.0*y/(x+y)*dp[x][y-1]);
}
return ans;
}
int main()
{
int a,b;
while(~scanf("%d%d",&a,&b))
{
printf("%.9f\n",dfs(a,b));
}
return 0;
}