纪中生活 1.1

今天又是模拟赛,明天就去听讲座了。

Test:0 最小花费

jzoj2125

(题目:n个人中,某些人的银行账号之间可以互相转账。这些人之间转账的手续费各不相同。给定这些人之间转账时需要从转账金额里扣除百分之几的手续费,请问A最少需要多少钱使得转账后B收到100元。

先预处理一下节点之间的权值,再跑最短路(建议用迪杰斯特拉,spfa可能会被数据卡。);

 

 

code:

#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;

int w,n,m,x,y,h,p[2005],k[2005];
double v,maxn,b[2005];

struct rect
{
    int to,next;
    double l;
}a[4000005];

int main()
{
    freopen("money.in", "r", stdin)
    freopen("money.out", "w", stdout);
    scanf("%d %d",&n,&m);
    for (int i = 1;i <= m;++i)
    {
        scanf("%d %d %lf",&x,&y,&v);
        a[++w].to = y;
          a[w].l = (100-v)/100;
          a[w].next = k[x];
          k[x] = w;
        a[++w].to = x;
          a[w].l =(100-v)/100;
          a[w].next = k[y];
          k[y]  = w;
    }
    scanf("%d %d",&x,&y);
    for (int i = k[x];i;i = a[i].next)
    {
        b[a[i].to] = a[i].l;
    }
    p[x] = 1;
    b[x] = 1;
    for (int i = 2;i < n;++i)
    {
        maxn = 0;
          h = 0;
        for (int j = 1;j <= n;++j)
        {
            if (!p[j]&&b[j] > maxn)
            {
                  maxn = b[j];
                  h = j;
            }
        }
        if (!h)
        {
            break;
        }
        p[h] = 1;
        for (int i = k[h];i;i = a[i].next)
        {
            if (!p[a[i].to]&&b[h]*a[i].l > b[a[i].to])
            {
                b[a[i].to] = b[h]*a[i].l;
            }    
        }    
    }
    printf("%.8lf",100/b[y]);
    return 0;
}

 

Test:1 最大约数和

jzoj2126

(题目:选取和不超过S(是<=1000)的若干个不同的正整数,使得所有数的约数(不含它本身)之和最大。)

简单,最优解用dp,先用一个sum数组储存s以前的数的因数和,再做01背包(sum[i]相当于价值,数字相当于重量,s相当于容量);

code:

#include<cstdio>
#include<iostream>
#include<cmath>
using namespace std;
int s;
int f[1000100];
int sum[1000100];
int main()
{
    freopen("maxsum.in", "r", stdin);
    freopen("maxsum.out", "w", stdout);
    scanf("%d",&s);  
    for(int i = 2;i <= s;++i)//2-s分解因数
    {
        for(int j = 1;j <= i-1;++j)
        {
            if(i % j==0)
            {
                sum[i]+=j;//求因数的和
            }
        }    
    }
    for(int i = 1;i <= s;++i)//0 1背包
    {
        for(int j = s;j >= i;--j)
        {
            f[j] = max(f[j],f[j-i]+sum[i]);
            
        } 
    } 
    printf("%d",f[s]);//输出最优解
    return 0;
}

 

Test:2 电子表格

jzoj2127

(题目:太长不想写,一眼看上去像是二维的线段树,但其实直接暴力就可以过。有四种操作:1.赋值 2.输出 3.将一个矩形区域的平均值赋值在一个数上 4.将一个矩形区域的和赋值在一个数上

code:

 

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
int a[200][52],in,m,n,s,wcs,w1s,w2s,jlsum[200][52][4],jlavg[200][52][4];
char wc,c[20],w1c,w2c;
bool sf[200][52],sf1[200][52];
int jsavg(int,int);
int jssum(int ax,int ay)
{
    if(jlsum[ax][ay][0]==-1 && jlavg[ax][ay][0]==-1)
    {
        sf[ax][ay]=1;
        return a[ax][ay];
    }
//    sf[ax][ay]=1;
    int all=0;
    for(int i=jlsum[ax][ay][0];i<=jlsum[ax][ay][2];i++)
        for(int j=jlsum[ax][ay][1];j<=jlsum[ax][ay][3];j++)
        {
            if(jlsum[i][j][0]!=-1) all+=jssum(i,j);
            else if(jlavg[i][j][0]!=-1) all+=jsavg(i,j);
            else all+=a[i][j];
        }
    a[ax][ay]=all;
    return all;
}
int jsavg(int ax,int ay)
{
    if(jlavg[ax][ay][0]==-1 && jlsum[ax][ay][0]==-1)
    {
        sf[ax][ay]=1;
        return a[ax][ay];
    }
//    sf[ax][ay]=1;
    int all=0;
    for(int i=jlavg[ax][ay][0];i<=jlavg[ax][ay][2];i++)
        for(int j=jlavg[ax][ay][1];j<=jlavg[ax][ay][3];j++)
        {
            if(jlsum[i][j][0]!=-1) all+=jssum(i,j);
            else if(jlavg[i][j][0]!=-1) all+=jsavg(i,j);
            else all+=a[i][j];
        }
    a[ax][ay]=all/((jlavg[ax][ay][2]-jlavg[ax][ay][0]+1)*(jlavg[ax][ay][3]-jlavg[ax][ay][1]+1));
    return a[ax][ay];
}
int main()
{
    freopen("excel.in","r",stdin);
    freopen("excel.out","w",stdout);
    cin>>m>>n>>s;
    memset(jlsum,-1,sizeof(jlsum));
    memset(jlavg,-1,sizeof(jlavg));
    while(s--)
    {
        cin>>wc;
        cin>>wcs>>c;
        int x=wcs,y=wc-'A'+1;
        if(c[0]=='i')
        {
            cin>>in;
            a[x][y]=in;
            for(int i=0;i<4;i++)
                jlsum[x][y][i]=-1,jlavg[x][y][i]=-1;
//            memset(sf,0,sizeof(sf));
//            memset(sf1,0,sizeof(sf1));
//            for(int i=1;i<=n;i++)
//                for(int j=1;j<=m;j++)
//                {
//                    
//                }
        }
        else if(c[0]=='o')
        {
            if(jlsum[x][y][0]!=-1) jssum(x,y);
            else if(jlavg[x][y][0]!=-1) jsavg(x,y);
            cout<<a[x][y]<<endl;
        }
        else if(c[0]=='s')
        {
            cin>>w1c>>w1s>>w2c>>w2s;
//            int all=0;
//            memset(sf,0,sizeof(sf));
//            memset(sf1,0,sizeof(sf1));
            jlsum[x][y][0]=w1s;
            jlsum[x][y][1]=w1c-'A'+1;
            jlsum[x][y][2]=w2s;
            jlsum[x][y][3]=w2c-'A'+1;
            for(int i=0;i<4;i++)
                jlavg[x][y][i]=-1;
//            jssum(x,y);
//            a[wcs][wc-'A'+1]=all;
        }
        else if(c[0]=='a')
        {
            cin>>w1c>>w1s>>w2c>>w2s;
//            int all=0;
//            memset(sf,0,sizeof(sf));
//            memset(sf1,0,sizeof(sf1));
//            a[wcs][wc-'A'+1]=all/((w2s-w1s+1)*(w2c-w1c+1));
            jlavg[x][y][0]=w1s;
            jlavg[x][y][1]=w1c-'A'+1;
            jlavg[x][y][2]=w2s;
            jlavg[x][y][3]=w2c-'A'+1;
            for(int i=0;i<4;i++)
                jlsum[x][y][i]=-1;
//            jsavg(x,y);
        }
    }
    return 0;
}

 

 

 

Test:3 X-因子链

jzoj2128

      首先我们将x 分解质因数 

      比如100=2^2*5^2

      然后我们用a 数组装下这些质数的次方

      第一的答案tot既为  a 数组的和    既2+2=4

      第二个答案用排列组合

      用tot的阶乘除(a[i]!*…a[m](a[i]<>0) 的阶乘)

      也就是4!/(2!*2!)

      既为第二个答案

      同时注意将1至20的阶乘全部求出来,方便直接调用。(题解)

code:

#include <cstdio>
#include <cctype>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
int main()
{
    freopen("factor.in","r",stdin);
    freopen("factor.out","w",stdout);
    ll x[25] = {1};
    for(ll i = 1;i < 25;++i)
    {
        x[i] =  i * x[i - 1];
    }
        
    ll n;
    scanf("%lld",&n);
    ll ans = 0,base = 1;
    for(ll i = 2;i * i <= n;++i)
    {
        if(n % i == 0)
        {
            ll cnt = 0;
            while(n % i == 0)
            {
                ++cnt;
                n /= i;
            }
            ans += cnt;
            base *= x[cnt];
        }
    }
    if(n > 1)
    {
        ans += 1;
    }        
    printf("%lld %lld",ans,x[ans] / base);
    return 0;
}

 

今天的题其实还挺简单的(前两题)so, 100|400分,rank 8

 

转载于:https://www.cnblogs.com/ouzijun-OJ/p/11371717.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值