2019杭电多校第七场

1001,1006,1011

1001: A + B = C

把后导零去掉之后,最大的那个数字一定是可以不动的(需要想一下),然后枚举a,b,c是否不动,设ta,tb,tc为a,b,c变动后的结果。
当c不动的时候,c的高位或次高位一定和ta或者tb高位对齐,枚举这四种清空。
当a不动的时候,a的最高位一定和c的最高位或者次高位对齐,枚举一下。
b和a同理。

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const ll mod = 1e9 + 7;
ll n, m;
bool pd(string& s, string& a){//a是否可以在s里面
    for(int i = 0; i < s.size(); ++i){
        if(i < a.size()) {
            if(s[i] != a[i]) return false;
        }
        else if(s[i]!='0') return false;
    }
    return true;
}
string a, b, c, ta, tb, tc, temp;
string sub(string str1,string str2)
{
	int len1=str1.size();
	int len2=str2.size();
	int jw=0,i,j;
	for(i=len1-1,j=len2-1;i>=0&&j>=0;i--,j--)
	{
		int num1=str1[i]-'0';
		int num2=str2[j]-'0';
		num1+=jw;
		if(num1-num2<0)
		{
			str1[i]=char('0'+10+num1-num2);
			jw=-1;
		}
		else
		{
			str1[i]=char('0'+num1-num2);
			jw=0;
		}
	}
	for(i;i>=0;i--)
	{
		int num1=str1[i]-'0';
		num1+=jw;
		if(num1>=0)
		{
			str1[i]=char('0'+num1);
			jw=0;
		}
		else
		{
			str1[i]=char('0'+10+num1);
			jw=-1;
		}
	}
	int biao=-1;
	string re;
	for(int i=0;i<len1;i++)if(str1[i]!='0'){biao=i;break;}
	if(biao==-1)return "0";
	for(int i=biao;i<len1;i++)re+=str1[i];
	return re;
}
int x, y ,z;
int dx, dy, dz;
int fnd;
void sol(string &a1, string &a2, string &a3, int &x1, int &y1){//a1不动,凑a3
    int len1 = a1.size(), len2 = a2.size(), len3 = a3.size();
    if(len1 < len2 || len1 < len3) return;//
    if(len1 == len2 && a1 < a2) return;
    if(len1 == len3 && a1 <= a3) return;
    tc = c;
    //和c对齐
    for(int i = 0; i < len1-len3; ++i) tc += "0";
    if(a1 < tc){
        temp = sub(tc, a1);
        if(pd(temp, a2)){
            fnd = 1; x1 = 0; y1 = temp.size() - a2.size(); z = len1-len3;return;
        }
    }
    //和c次位对齐
    while(tc.size() < len1+1) tc += "0";
    temp = sub(tc, a1);
    if(pd(temp, a2)){
        fnd = 1; x1 = 0; y1 = temp.size() - a2.size(); z = len1-len3+1;
    }
}
void pro(string &t, int& d){
    int i;
    for(i = t.size()-1; i >= 0; --i) if(t[i] != '0') break;
    d = (i+1)-t.size();
    t = t.substr(0, i+1);
    return;
}
int main()
{
    ios::sync_with_stdio(false);
    int T;cin>>T;
    while(T--){
        cin>>a>>b>>c;
        dx = dy = dz = 0;
        pro(a, dx); pro(b, dy); pro(c, dz);
        //cout<<a<<" "<<b<<" "<<c<<endl;
        fnd = 0;
        int lena = a.size(), lenb = b.size(), lenc = c.size();
        if(lenc >= lena && lenc >= lenb){//c不动
            int ok = 1;
            if(lenc == lena && a >= c) ok = 0;
            if(lenc == lenb && b >= c) ok = 0;
            if(ok){//c是最大的数
                //和a次对齐
                if(lenc > lena){
                    ta = a;
                    for(int i = 0; i < lenc-lena-1; ++i) ta+="0";
                    temp = sub(c, ta);
                    if(pd(temp, b)){
                        fnd = 1; x = lenc-lena-1; y = temp.size() - b.size(); z = 0;
                    }
                }
                //和a对齐
                ta = a;
                while(ta.size() < lenc) ta += "0";
                if(c > ta){
                    temp = sub(c, ta);
                    if(pd(temp, b)){
                        fnd = 1; x = lenc-lena; y = temp.size() - b.size(); z = 0;
                    }
                }
                //和b次对齐
                if(lenc > lenb){
                    tb = b;
                    for(int i = 0; i < lenc-lenb-1; ++i) tb+="0";
                    temp = sub(c, tb);
                    if(pd(temp, a)){
                        fnd = 1; x = temp.size() - a.size(); y = lenc-lenb-1; z = 0;
                    }
                }
                //和b对齐
                tb = b;
                while(tb.size() < lenc) tb+="0";
                if(c > tb){
                    temp = sub(c, tb);
                    if(pd(temp, a)){
                        fnd = 1; x = temp.size() - a.size(); y = lenc-lenb; z = 0;
                    }
                }
            }
        }
        sol(a,b,c,x,y);
        sol(b,a,c,y,x);
        if(!fnd){
            printf("-1\n");continue;
        }
        else{
            x = x+dx; y = y+dy; z = z+dz;
            int mi = min(x,y);
            mi = min(mi, z);
            x -= mi; y -=mi; z -= mi;
            printf("%d %d %d\n", x, y, z);
        }
    }
}
/*
1
2 11 112
*/

1006: Final Exam

题意有点绕,意思是:消灭一个数x需要x的代价,你要给n个数字分配数值,你如何分配使得分配数值的总额最小,并且消灭(n-k+1)个数字的最小代价大于m。
消灭(n-k+1)个数字的最小代价一定是最小的(n-k+1)的数字之和。那么我们只要让这个值为m+1,并且让其中最大的那个最小。平均分配即可。剩下的k-1个数字的值都是那个最大值。

#include<bits/stdc++.h>
#define ll long long
using namespace std;
int main()
{
	int T;cin>>T;
	while(T--){
        ll n, m, k;
        scanf("%lld%lld%lld", &n, &m, &k);
        ll ans = m+1;
        if((m+1)%(n-k+1)==0) ans += (k-1)*(m+1)/(n-k+1);
        else ans += (k-1)*((m+1)/(n-k+1) + 1);
        printf("%lld\n", ans);
	}
}

1011:Kejin Player

设dp[i]为i升级到i+1的期望花费,则 d p [ i ] = a i + ( 1 − p i ) Σ j = x i i d p [ i ] dp[i]=a_i+(1-p_i)\Sigma_{j=x_i}^{i}dp[i] dp[i]=ai+(1pi)Σj=xiidp[i]
p i ∗ d p [ i ] = a i + ( 1 − p i ) Σ j = x i i − 1 d p [ i ] p_i*dp[i]=a_i+(1-p_i)\Sigma_{j=x_i}^{i-1}dp[i] pidp[i]=ai+(1pi)Σj=xii1dp[i]
前缀和记录一下dp的累加值。然后每次查询[l,r]等于 Σ i = l r − 1 d p [ i ] \Sigma_{i=l}^{r-1}dp[i] Σi=lr1dp[i]

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn = 5e5 + 50;
const int mod = 1e9 + 7;
void read(ll &x){
    x = 0;
    char ch = getchar();
    while(ch < '0' || ch > '9') ch = getchar();
    while(ch <= '9' && ch >= '0') x = x*10 + ch - '0', ch = getchar();
    return ;
}
ll qm(ll a, ll b){
    ll res = 1;
    while(b){
        if(b&1) res = 1LL*res*a%mod;
        a = 1LL*a*a%mod;
        b>>=1;
    }
    return res;
}
int n, q;
ll dp[maxn];
ll sum[maxn];
int main()
{
	int T;cin>>T;
	while(T--){
        scanf("%d%d", &n, &q);
        dp[0] = sum[0] = 0;
        for(int i = 1; i <= n; ++i){
            ll r, s, x, a;
            read(r); read(s); read(x); read(a);
            ll p = r*qm(s, mod-2)%mod;
            dp[i] = a;
            dp[i] = (dp[i] + (1-p)*(sum[i-1] - sum[x-1])%mod )%mod;
            dp[i] = dp[i] * qm(p, mod-2)%mod;
            dp[i] = (dp[i] + mod)%mod;
            sum[i] = (sum[i-1] + dp[i])%mod;
           // cout<<"i:"<<i<<" dp:"<<dp[i]<<endl;
        }
        while(q--){
            ll l, r;
            read(l); read(r);
            ll ans = (sum[r-1] - sum[l-1])%mod;
            ans = (ans + mod)%mod;
            printf("%lld\n", ans);
        }
	}
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值