UPC-混合训练第十五场

gift

题目描述
战争结束,A国和B国的元首决定两国友好相处,于是城市之间就有互相送礼的情况。
参与这次相互协助计划中有n个A国的城市和m个B国的城市。作为A国的重臣,小Q了解到每一个A国的城市送出了ai份礼物,B国的城市收到了bi份礼物,城市之间不会重复送礼,并且A国和B国自己的城市之间不会送礼。
有一句老话“眼见为实,耳听为虚”,现在小Q想知道是否存在一种送礼的方案使得每一个城市都满足要求。
输入
第一行一个整数T,表示小Q询问的次数。
接下来有T组询问,每一组询问第一行为两个正整数n,m,表示A国的城市数和B国的城市数。
第二行给出n个整数ai,表示A国第i个城市送出的礼物数。
第三行给出n个整数bi,表示B国第i个城市收到的礼物数。
输出
共T行,每行输出Yes或No表示是否存在一种合法方案。
样例输入 Copy

3
1 2
2
1 1
2 2
1 1
1 2
5 2
2 1 1 1 0
0 5

样例输出 Copy

Yes
No
No

提示
样例解释
第一组数据中A国只有一个城市,送给B国两个城市共两个礼物。
第二组数据中A国总共送出2个礼物,但是B国共收到3个,显然矛盾。
第三组数据中A国的第一个城市给B国的第二个城市送了超过一个礼物,矛盾。
对于100%的数据,满足T≤10,1≤n,m≤1000,0≤ai≤m,0≤bi≤n。

根据通过率来看,此题有坑,首先我个人来说没有看见B国的城市只能是接受A国一个城市的礼物,换句话说就是B只能接受一个礼物,不能接受两个礼物本蒟蒻在这里卡了9%
然后暴力了一波之后发现,通过不了

根据dl的神仙思路,统计A中的最大值、最小值、和、非零个数
统计B中非零的个数、等于n的个数、和
如果两方的数量和不相同,那么必定就是No
如果B中的元素大小如果超过A中的非零的个数,那么就意味着B中一定是会接手两个A的礼物,因此,这种情况必定是No
如果A中最大大于B里面非零的个数,也是No
如果B里面等于n的个数大于A中的最小值,这种情况也是No

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define HEAP(...) priority_queue<__VA_ARGS__ >
#define heap(...) priority_queue<__VA_ARGS__,vector<__VA_ARGS__ >,greater<__VA_ARGS__ > >
template<class T> inline T min(T &x,const T &y){return x>y?y:x;}
template<class T> inline T max(T &x,const T &y){return x<y?y:x;}
ll read(){ll c = getchar(),Nig = 1,x = 0;while(!isdigit(c) && c!='-')c = getchar();
if(c == '-')Nig = -1,c = getchar();
while(isdigit(c))x = ((x<<1) + (x<<3)) + (c^'0'),c = getchar();
return Nig*x;}
#define read read()
const ll inf = 1e15;
const ll INF = 0x3f3f3f3f;
const int maxn = 3e5 + 7;
const int mod = 998244353;
#define pi 3.14159265358979323846
ll gcd(ll a,ll b)
{
    ll t;
    while(b!=0)
    {
        t=a%b;
        a=b;
        b=t;
    }
    return a;
}
ll qPow(ll x, ll k)
{
    ll res = 1;
    while(k) {
        if(k&1)
            res=(res*x);
        k>>=1;
        x=(x*x);
    }
    return res;
}
ll maxx=-1;
ll minn=inf;
ll num[maxn];
ll num2[maxn];
ll res,ans;
map<string,ll> mp;
priority_queue <int ,vector<int> ,greater<int> > xiaogen;
deque<int> q;
ll a[maxn],b[maxn];
ll wrkc[502][502];
int main()
{
    ///gift
    int T=read;
    while(T--){
        int n=read,m=read;
        ll sum1=0;
        ll sum2=0;
        int flag=1;
        maxx=0,minn=INF;
        int cnt1=0,cnt2=0,cnt3=0;
        for(int i=1;i<=n;i++){
            a[i]=read;
            sum1+=a[i];
            if(a[i]>maxx) maxx=a[i];
            if(a[i]){
                cnt1++;
                if(minn>a[i]) minn=a[i];
            }
        }
        for(int i=1;i<=m;i++){
            b[i]=read;
            if(b[i]) cnt2++;
            if(b[i]>cnt1) flag=0;
            sum2+=b[i];
            if(b[i]==n) cnt3++;
        }
        if(sum1!=sum2) flag=0;
        if(cnt3>minn) flag=0;
        if(maxx>cnt2) flag=0;
        if(flag) printf("Yes\n");
        else printf("No\n");
    }
    return 0;
}
/**
3
1 2
2
1 1
 
2 2
1 1
1 2
 
5 2
2 1 1 1 0
0 5
**/
 
/**************************************************************
    Problem: 15362
    Language: C++
    Result: 正确
    Time:2 ms
    Memory:13380 kb
****************************************************************/

魔法阵

题目描述
很久以前,遥远的盘古大陆有三个村:苹果村、梨子村和香蕉村
有一天,伟大的魔法师kiwi发明了一种魔法阵,如下图

苹果村有A个村民,梨子村有B个村民,香蕉村有C个村民
苹果村每个村民有a[i]个苹果,梨子村每个村民有b[i]个梨子,香蕉村每个村民有c[i]个香蕉
Kiwi会选择三个村的村民各一个,每个村民会从自己拥有的水果中任意选择应有的数量个(苹果3个,梨子2个,香蕉1个)放入魔法阵中
Kiwi认为每个水果都是不同的,两个魔法阵不同当且仅当放入的水果至少有一个不同
也就是说,与每个水果在魔法阵中的位置无关
Kiwi想知道魔法阵一共可能有多少种,对998244353取模
输入
第一行3个数A,B,C
第二行A个数表示a[i]
第三行B个数表示b[i]
第四行C个数表示c[i]
输出
一行表示魔法阵一共可能有多少种,对998244353取模
样例输入

1 2 1
3
2 3
1

样例输出

4

提示
Kiwi只能选择仅有的苹果村村民和香蕉村村民,而他们也只能拿出全部的水果
如果他选择了第1个梨子村村民,那么他也只能拿出全部梨子
如果他选择了第2个梨子村村民,设他的梨子分别叫1,2,3,那么他可以拿{1,2}{1,3}{2,3}
a[i]>=3,b[i]>=2,c[i]>=1
对于前30%的数据:A,B,C,a[i],b[i],c[i]<=6
对于前60%的数据:A,B,C<=100,a[i],b[i],c[i]<=20
对于前80%的数据:A,B,C<=2000
对于100%的数据:A,B,C<=100000,a[i],b[i],c[i]<=500

这就是组合数比较裸的题,根据高中的分类加法分步乘法来说,先分别统计A B C中各有多少种方法,然后再将这三种方法相乘就是最终结果
需要注意的是数据可能很大请不要吝啬趋于,否则容易40%

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define HEAP(...) priority_queue<__VA_ARGS__ >
#define heap(...) priority_queue<__VA_ARGS__,vector<__VA_ARGS__ >,greater<__VA_ARGS__ > >
template<class T> inline T min(T &x,const T &y){return x>y?y:x;}
template<class T> inline T max(T &x,const T &y){return x<y?y:x;}
ll read(){ll c = getchar(),Nig = 1,x = 0;while(!isdigit(c) && c!='-')c = getchar();
if(c == '-')Nig = -1,c = getchar();
while(isdigit(c))x = ((x<<1) + (x<<3)) + (c^'0'),c = getchar();
return Nig*x;}
#define read read()
const ll inf = 1e15;
const ll INF = 0x3f3f3f3f;
const int maxn = 3e5 + 7;
const int mod = 998244353;
#define pi 3.14159265358979323846
ll gcd(ll a,ll b)
{
    ll t;
    while(b!=0)
    {
        t=a%b;
        a=b;
        b=t;
    }
    return a;
}
ll qPow(ll x, ll k)
{
    ll res = 1;
    while(k) {
        if(k&1)
            res=(res*x);
        k>>=1;
        x=(x*x);
    }
    return res;
}
ll maxx=-1;
ll minn=inf;
ll num[maxn];
///ll a[maxn];
ll num2[maxn];
ll res,ans;
map<string,ll> mp;
priority_queue <int ,vector<int> ,greater<int> > xiaogen;
deque<int> q;
ll a[maxn],b[maxn],c[maxn];
ll wrkc[502][502];
int main()
{
    for(int i=0;i<=501;i++){
        wrkc[i][i]=1;
        wrkc[i][0]=1;
    }
    for(int i=1;i<=501;i++){
        for(int j=1;j<i;j++){
            wrkc[i][j]=(wrkc[i-1][j]%mod+wrkc[i-1][j-1]%mod)%mod;
        }
    }
    ///cout<<wrkc[6][2]<<endl;
    int aa=read,bb=read,cc=read;
    for(int i=1;i<=aa;i++) a[i]=read;
    for(int i=1;i<=bb;i++) b[i]=read;
    for(int i=1;i<=cc;i++) c[i]=read;
    ans=1;
    ll temp1=0,temp2=0,temp3=0;
    for(int i=1;i<=aa;i++){
            temp1+=wrkc[a[i]][3]%mod;
            temp1%=mod;
    }
    for(int i=1;i<=bb;i++){
            temp2+=wrkc[b[i]][2]%mod;
            temp2%=mod;
    }
    for(int i=1;i<=cc;i++){
        temp3+=c[i]%mod;
        temp3%=mod;
    }
    ans=(temp1%mod)*(temp2%mod)%mod*temp3%mod;
    cout<<ans%mod<<endl;
    return 0;
}
/**
1 2 1
3
2 3
1
**/
 
/**************************************************************
    Problem: 15364
    Language: C++
    Result: 正确
    Time:27 ms
    Memory:15724 kb
****************************************************************/
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值