【浮*光】【Codeforces Round #491 (Div. 2)】A,B,C,D,E

A. If at first you don't succeed...

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

/*【A. If at first you don't succeed...】
通过考试的人中,A名学生去了a餐厅,B名学生去了b餐厅,C名学生去了这两家餐厅。
团队有N名学生。根据这个信息,Vasya想要确定他的数据是否自相矛盾,
或者,如果不矛盾,他的小组中有多少学生没有通过考试。 */

int n,a,b,c;
int main() {
    scanf("%d%d%d%d",&a,&b,&c,&n);
    int p = a+b-c;
    if(a>=c&&b>=c&&n-p>=1) printf("%d\n",n-p);
    else printf("-1\n");
    //↑↑↑注意:自相矛盾不只有一个条件
    return 0;
}

B. Getting an A

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

/*【B. Getting an A】
将计算出学期所有分数的平均值,并四舍五入到最近的整数。
Vasya想要重做尽可能少的实验室工作,以获得5分。 */

//平均超过4.5分即可。

int n,a[109],sum=0;

int main(){
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        scanf("%d",&a[i]);
        sum+=a[i];
        a[i]=5-a[i]; //剩下能弥补的分数
    }
    sort(a+1,a+1+n); //从小到大
    
    double now=4.5*(double)n-sum;
    if(now<=0) cout<<"0"<<endl;
    else{
        if((int)(now*2)%2!=0) now+=0.5;
        int nn=n;
        while(now>0){
            now-=a[nn]; nn--; 
        }
        printf("%d\n",n-nn);
    }
    return 0;
}

C. Candies

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

/*【C. Candies】
n个糖果,每天早上吃等量k个的糖果,在晚上吃掉盒子里剩下的10%的糖果。
你的任务是找出最小k,使早上吃的糖果至少占n个糖果的一半。注意,数字k必须是整数。 */

//每次减少10%会使数减小的非常快,二分k,模拟

ll n;
int A[10000];

int midk(ll k){ //判断(二分k)能否成立的函数
    ll now=n,x,res=0;
    while(now){ //模拟过程
        if(now<k) res+=now,now=0; //全部吃掉了
        else now-=k,res+=k; //还有剩余
        if(now>=10){ //晚上吃的
            x=now/10; now-=x;
        }
    }
    return (res*2LL >= n); //早上吃的*2 >= 总数
}


int main(){
    cin>>n; ll l=1,r=n,ans,mid; 
    while(l<=r){ //二分答案
        mid=(l+r)/2LL; //longlong型的2
        if(midk(mid)) r=mid-1,ans=mid;
        else l=mid+1;
    }
    cout<<ans<<endl;
    return 0;
}

D. Bishwock

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

/*【D. Bishwock】
给你一个2*n的棋盘,X表示障碍,问你可以往这个棋盘上放上多少个L型积木。  */

char s1[105],s2[105]; //上下两行

int main(){
    int ans=0; cin>>s1>>s2;
    int len=strlen(s1); //得到列数n的大小
    for(int i=0;i<len;i++){ //直接搜索4种L型
        if(s1[i]=='0'&&s2[i]=='0'&&s1[i+1]=='0') 
            s1[i]=s1[i+1]=s2[i]='x',ans++;
        else if(s1[i]=='0'&&s2[i]=='0'&&s2[i+1]=='0') 
            s1[i]=s2[i]=s2[i+1]='x',ans++;
        else if(s1[i]=='0'&&s1[i+1]=='0'&&s2[i+1]=='0') 
            s1[i]=s1[i+1]=s2[i+1]='x',ans++;
        else if(s2[i]=='0'&&s1[i+1]=='0'&&s2[i+1]=='0') 
            s2[i]=s1[i+1]=s2[i+1]='x',ans++;
    }
    cout<<ans<<endl;
}

E. Bus Number

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

/*【E. Bus Number】
如果看到数字2028,它可能意味着实际的车号可能是2028,8022,2820或者仅仅是820。
然而,80号、22208号、52号肯定不是这辆车的号码。
而且,实际的车号不能以数字0开头,例如,数字082不能也是实际的车号。
给定看到的数字n,求出所有可能的车号种数。 */


/*【分析】
1.统计0~9出现的次数,按题意枚举每个数分别出现多少个,
对于每个情况设一共有sum个数字,A[i]为数字i出现的次数,
那么有sum!/(A[0]!*A[1]!*...*A[9]!)种[不考虑前导0情况下]
2.考虑计算有前导0的情况,把非0的数仿照上边的方法求出排列数,
然后把一个0放到开头固定,剩余的0插空放在这sum个数之间即可,
把上面两个值相减就是答案。  */

int num[10],tempNum[10];
ll jc[20],ans=0; //阶乘求出来的值用jc数组记录 

void dfs(int x){ //从0~9寻找各数字的出现
    if(x==10){ //0~9都寻找完毕了
        int cnt=0; //cnt记录所有数字的个数
        for(int i=0;i<10;++i) cnt += tempNum[i];
        
        ll p=jc[cnt]; //p为这种情况的临时记录变量
        for(int i=0;i<10;++i) p/=jc[tempNum[i]];
        //↑↑↑ sum!/(A[0]!*A[1]!*...*A[9]!)
        if(tempNum[0]>=1) p-=(p*tempNum[0]/cnt); 
        
        ans+=p; return; //完成计算,返回答案
    }
    for(int i=1;i<=num[x]; ++i){
        tempNum[x]=i; dfs(x+1); //某看到的数字可能有1~num个 
        //【巧妙】直接用递归解决多层次的问题
    }
    if(num[x]==0) dfs(x+1);
}

int main(){
    string s; cin>>s; //字符串用于输入
    int len=s.size(); //↓↓求出现次数
    for(int i=0;i<len;i++) num[s[i]-'0']++; 
    jc[0]=1; //阶乘
    for(int i=1;i<=19;i++) jc[i]=jc[i-1]*i; //ll存的下
    dfs(0); cout<<ans<<endl;
    return 0;   
}


                                                                                ——时间划过风的轨迹,那个少年,还在等你。

猜你喜欢

转载自blog.csdn.net/flora715/article/details/81033771