2019 杭电多校(第七场)

1001 A + B = C

http://acm.hdu.edu.cn/showproblem.php?pid=6646

题意

给你三个数 A B C,问能否给他们每个乘若干次10 能否满足A + B = C

思路

A + B = C 他们位数只有四种情况 (1 n + n = n (2 (n+1) + n = n+1 (3  n + (n+1) = n+1 (4 n + n = (n+1)  

依次判断即可 (判断加法是否满足可以用hash)

队友代码

#include 
#define ll long long
using namespace std;
const int maxn = 2e5;
string ck(string a,string b)
{
    int ta[maxn],tb[maxn];
    memset(ta,0,sizeof(ta));
    memset(tb,0,sizeof(tb));
    int lena=a.size(),lenb=b.size();
    for(int i=0; i0&&ta[len]==0)
        len--;
    for(int i=0; i<=len; i++)
        ans+=ta[i]+'0';
    return ans;
}
int main()
{
    int t,x,y,z;
    string a,b,c;
    ios::sync_with_stdio(0);
    cin>>t;
    while(t--)
    {
        x=0,y=0,z=0;
        cin>>a>>b>>c;
        int lena=a.size(),lenb=b.size(),lenc=c.size();
        int len=2e5;
        while(lenc1)
        {
            cha--;
            temp+="0";
            x++;
        }
        temp+=a;
        string s=ck(c,temp);
        int lens=s.size(),lent;
        string tepb;
        lent=lenb;
        while(lent1)
        {
            cha--;
            temp+="0";
            y++;
        }
        temp+=b;
        s=ck(c,temp);
        lens=s.size();
        tepb.clear();
        lent=lena;
        while(lent

1006 Final Exam (思维)

http://acm.hdu.edu.cn/showproblem.php?pid=6651

题意

n门课程 m分总分 要通过k门课程 

通过课程的条件是复习时间大于课程分数 

现在不知道分数分配情况 问最小需要复习多少时间一定能通过k门课程

思路

最差的情况即m分让你复习时间最少的n-k门课程有一门不能通过

那么复习时间要让最少的n-k门课程最和大于m 那么k门课程课程复习最少时间即(n-k)门中时间最多的

为了让(n-k)门课程复习时间最多的最少 就要平均分配时间

代码

#include 

using namespace std;
const int maxn = 1e5+100;
typedef long long ll;

int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        ll n,m,k;
        scanf("%lld%lld%lld",&n,&m,&k);
        ll ans;
        if(m + k < n)
        {
            ans = m + k;
        }
        else
        {
            ll x = (m) / (n-k+1);
            x++;
            ans = x*(k-1) + m + 1;
        }
        printf("%lld\n",ans);
    }
    return 0;
}

1010 Just Repeat

http://acm.hdu.edu.cn/showproblem.php?pid=6655

题意

不想描述了

思路

题解 “每个人优先出的牌的颜色肯定是场上没出过的, 对方也持有的, 并且两个人手中持有数量最多

的牌.对方持有的越多意味着可以封掉更多的牌, 而自己手里的越多意味着可以防止自己更多的牌

被封掉.

因此, 对所有两个人手里都持有的颜色的牌数进行统计, 从大到小依次分配给第一, 第二个玩家.

如果此时第一个玩家手里的牌数 > 第二个玩家, 则第一个玩家胜利, 否则第二个玩家胜利.

到此为止, 问题转换成另一个问题, 就是有一堆东西, 每个东西有两个值, A 拿到这个东西的收

益是 ai , B 拿到的收益是 bi.两人依次拿.求最优策略下两人的各自收益.这是一个经典问题,

案就是按照 ai + bi 排序模拟一下就好了.至于这样做是正确的理由, 那就留给读者思考了.

由于出题人比较变态, 直接上 map 可能会 T, 单纯用 cin 是没什么问题的, 只要你别其他地方

也都写得很慢, 还慢大常数倍的那种.

代码

#include 

using namespace std;
const int maxn = 1e5+100;
typedef long long ll;
typedef unsigned long long ull;
unordered_map mp;
struct node
{
    int x,x1,x2;
}aa[maxn*2];

int n,m,op;
int a[maxn],b[maxn];
ull k1,k2;

bool cmp(node a,node b)
{
    return a.x > b.x;
}
ull rng() {
    ull k3 = k1, k4 = k2;
    k1 = k4;
    k3 ^= k3 << 23;
    k2 = k3 ^ k4 ^ (k3 >> 17) ^ (k4 >> 26);
    return k2 + k4;
}
void read1(ull mod)
{
    for(int i = 0;i < n;i++)
    {
        a[i+1] = rng() % mod;
    }
}
void read2(ull mod)
{
    for(int i = 0;i < m;i++)
    {
        b[i+1] = rng() % mod;
    }
}

int main()
{
    ios::sync_with_stdio(false);
    int T;
    cin>>T;
    while(T--)
    {
        cin>>n>>m>>op;
        if(op==1){
            for(int i = 1;i <= n;i++) cin>>a[i];
            for(int i = 1;i <= m;i++) cin>>b[i];
        }
        else{
            ull mod;
            cin>>k1>>k2>>mod;
            read1(mod);
            cin>>k1>>k2>>mod;
            read2(mod);
        }
        mp.clear();
        int p = 0;
        for(int i = 1;i <= n;i++)
        {
            if(mp[a[i]] == 0){
                mp[a[i]] = ++p;
                aa[p].x1 = 1;
                aa[p].x2 = 0;
            }
            else{
                int id = mp[a[i]];
                aa[id].x1++;
            }
        }
        for(int i = 1;i <= m;i++)
        {
            if(mp[b[i]] == 0){
                mp[b[i]] = ++p;
                aa[p].x1 = 0;
                aa[p].x2 = 1;
            }
            else{
                int id = mp[b[i]];
                aa[id].x2++;
            }
        }
        for(int i = 1;i <= p;i++) aa[i].x = aa[i].x1 + aa[i].x2;
        sort(aa+1,aa+1+p,cmp);
        int suma=0,sumb=0;
        op = 1;
        for(int i = 1; i <= p;i++)
        {
            if(aa[i].x1 == 0) {sumb += aa[i].x2;continue;}
            if(aa[i].x2 == 0) {suma += aa[i].x1;continue;}
            if(op==1) suma += aa[i].x1;
            else sumb += aa[i].x2;
            op ^= 1;
//            cout< sumb) cout<<"Cuber QQ"<

1011 Kejin Player (期望)

http://acm.hdu.edu.cn/showproblem.php?pid=6656

题意

花费a[i]可以升一次级 有p的几率成功 不成功会掉的x[i]级 为从l升到r期望花费是多少

思路

线性递推 dp[i] = p*a[i] + (1-p)(a[i] + xx + dp[i])

其中dp[i]表示 i 升 i+1 的期望花费 xx表示从掉的级升到当前的花费(前缀和) 

代码

#include 
using namespace std;
typedef long long ll;
const ll maxn = 6e5;
const ll mod = 1e9+7;
ll r[maxn],s[maxn],x[maxn],a[maxn];
ll sum[maxn],num[maxn];

ll qpow(ll x,ll n)
{
    ll ans = 1;
    while(n)
    {
        if(n%2)
        {
            ans = ans * x % mod;
        }
        x = x * x % mod;
        n /= 2;
    }
    return ans;
}

int main()
{
    ll T;
    scanf("%lld",&T);
    while(T--)
    {
        ll n,m;
        scanf("%lld%lld",&n,&m);
        for(ll i = 1;i <= n;i++)
        {
            scanf("%lld%lld%lld%lld",&r[i],&s[i],&x[i],&a[i]);
        }
        for(ll i = 1;i <= n;i++)
        {
            ll xx = sum[i-1]-sum[x[i]-1];

            ll p = r[i] * qpow(s[i],mod-2) % mod;

            ll qwe = (((a[i] + xx)*qpow(p,mod-2) - xx)%mod+mod)%mod;

            sum[i] = (sum[i-1] + qwe)%mod;

        }
        while(m--)
        {
            ll l,r;
            scanf("%lld%lld",&l,&r);
            ll ans = sum[r-1] - sum[l-1];
            ans = (ans + mod) % mod;
            printf("%lld\n",ans);
        }
    }
    return 0;
}

 

你可能感兴趣的:(#,2019,杭电多校)