题目链接:https://vjudge.ppsucxtt.cn/contest/76505#problem/A
题目:LightOJ - 1027
题目思路:
按照样例解释
3
-3 -6 -9
d=1/33+1/3(6+d)+1/3*(9+d)
化简得d=time(总时间)/(n-cnt)//cnt为负数的个数
代码:
#include<iostream>
#include<cstring>
#include<string.h>
#include<queue>
#include<algorithm>
using namespace std;
typedef long long int ll;
const int maxn = 800000;
int test,cas=1;
int num[maxn];
int cnt;
int n;
int gcd(int a, int b) {
return a == 0 ? b : gcd(b % a, a);
}
void solve() {
int t = 0;
for(int i = 0; i < n; i++)
t = t + (num[i] > 0 ? num[i] : -num[i]);
int g = gcd((n - cnt), t);
// cout<<(n-cnt)<<" "<<t<<endl;
printf("%d/%d\n", t / g, (n - cnt) / g);
}
int main()
{
scanf("%d", &test);
while(test--){
scanf("%d", &n);
cnt=0;
for(int i=0;i<n;i++){
scanf("%d", &num[i]);
if(num[i]<0){
cnt++;
}
}
printf("Case %d: ", cas++);
if(cnt==n){
printf("inf\n");
continue;
}
/*int sum=0;
for(int i=1;i<=n;i++){
sum+=abs(num[i]);
}
int g=gcd((n-cnt),sum);
//cout<<(n-cnt)<<" "<<sum<<endl;
printf("%d/%d\n",sum/g,(n-cnt)/g);*/
solve();
}
return 0;
}
题目: LightOJ - 1030
题目思路:首先是肯定能到达的位置为开头和结尾,其次计算出到达每个位置得概率乘以相应位置黄金数量,得出结果
代码:
#include<iostream>
#include<cstring>
#include<string.h>
#include<queue>
#include<algorithm>
using namespace std;
typedef long long int ll;
const int maxn = 800000;
int t;
int n;
int a[maxn];
double sum=0;
int cas=1;
double p[maxn];
int main()
{
scanf("%d",&t);
while(t--){
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
}
sum=0.0;
memset(p,0,sizeof(p));
if(n!=1)sum+=(a[1]+a[n]);
else sum+=a[1];
p[1]=1;
for(int i=1;i<n;i++){
int d=n-i;
if(d<6){
double k=1.0/(d*1.0);
for(int j=1;j<=d;j++){
p[i+j]+=p[i]*k;
}
}else{
double k=1.0/6;
for(int j=1;j<=6;j++){
p[i+j]+=p[i]*k;
}
}
}
for(int i=2;i<n;i++){
sum+=p[i]*a[i];
}
//printf("Case %d: %.6f\n",++cas,sum);
printf("Case %d: %.6f\n", cas++, sum);
}
return 0;
}
题目:LightOJ - 1038
题目思路:由下而上进行递推计算,主要是加上自身得情况
参考链接:https://blog.csdn.net/guagua_de_xiaohai/article/details/87536131
代码:
#include<iostream>
#include<cstring>
#include<string.h>
#include<queue>
#include<algorithm>
using namespace std;
typedef long long int ll;
const int maxn =1e5+10;
int t;
int n;
double dp[maxn];
void init(){
dp[1]=0.0;
for(int i=2;i<=maxn;i++){
dp[i]=0.0;
int cnt=0;
for(int j=1;j*j<=i;j++){
if(i%j==0&&(i/j)!=j){
cnt+=2;
dp[i]+=2+dp[j]+dp[i/j];
}
if(j*j==i){
cnt++;
dp[i]+=dp[j]+1;
}
}
dp[i]/=(cnt-1);//处理自身情况
}
}
int main()
{
init();
scanf("%d",&t);
int cas=0;
while(t--){
scanf("%d",&n);
printf("Case %d: %.7lf\n",++cas,dp[n]);
}
return 0;
}
题目:LightOJ - 1079
题目思路:01背包问题,通过计算逃跑的概率,因为要抢多家银行,自然是计算能逃出得概率,同时逃出得概率相互独立,即抢i和j两家银行逃出的概率为(1-p[i])*(1-p[j]),通过dp[j],即为抢劫j钱后逃出得概率来逆推出结果
代码:
#include<iostream>
#include<cstring>
#include<string.h>
#include<queue>
#include<algorithm>
using namespace std;
typedef long long int ll;
const int maxn =100*100+100;
int t,cas;
int n;
int v[maxn];
double dp[maxn],p[maxn],P;
int sum=0;
int main()
{
cas=1;
scanf("%d",&t);
while(t--){
memset(dp,0.0,sizeof(dp));
scanf("%lf%d",&P,&n);
for(int i=1;i<=n;i++){
scanf("%d%lf",&v[i],&p[i]);
sum+=v[i];
}
dp[0]=1.0;
for(int i=1;i<=n;i++){
for(int j=sum;j>=v[i];j--){
dp[j]=max(dp[j],dp[j-v[i]]*(1-p[i]));
}
}//01背包
for(int i=sum;i>=0;i--){//逆推
if(dp[i]>=(1-P)){
printf("Case %d: %d\n",cas++,i);
break;
}
}
sum=0;
}
return 0;
}