cf#392

166 篇文章 0 订阅
5 篇文章 0 订阅

http://codeforces.com/contest/758

2017第一场。。。。才三道题,,,还wa了好多发。。。赛后补了DF

A题:

题意:

全部补成一个数,加多少个数

tip:

找最大值

#include <cstdio>
#include <iostream>
#include <cmath>
#include <cstring>
using namespace std;
int main(){
    int n;
    scanf("%d",&n);
    int minn = 0,sum=0;
    for(int i = 1 ; i <= n ; i++){
        int a;
        scanf("%d",&a);
        minn = max(minn,a);
        sum += a;
    }
    printf("%d\n",minn*n-sum);
}

B题:

题意:

4个灯泡按着顺序排列,其中有一些问号。。。保证每个灯泡都出现至少一次,
分别输出RBYG多少个是问号

tip:

可以看出%之后的值,每个数都对应同一个颜色的灯泡,那么就可以算出来

#include <cstdio>
#include <iostream>
#include <cmath>
#include <cstring>
using namespace std;
char s[110],mp[5];
int book[5],a[5];
int main(){
    scanf("%s",s);
    for(int i =  0 ; i < strlen(s);i++){
        int k = i%4;
        if(s[i]!='!')   mp[k] = s[i];
        else   book[k]++;
    }
    for(int i = 0 ; i < 4;i++){
        if(mp[i]=='R')
            a[0] = book[i];
        if(mp[i]=='B')
            a[1] = book[i];
        if(mp[i]=='Y')
            a[2] = book[i];
        if(mp[i]=='G')
            a[3] = book[i];
    }
    for(int i = 0 ; i < 4 ;i++)
        printf("%d%c",a[i],i==3?'\n':' ');
}

C题:

题意:

老师提问,次数最多,最少,和固定位置的人被提问了多少次。

tip:

就是各种问题,欸。。。第一排和最后一排比较特殊,然后可以发现先n*m个人提问之后,(n-1)*m*2是一个循环,每个循环,第一行和最后一行的人被提问一次,其他两次,在判断剩下的是在从下到上还是从上到下的过程,在判断能不能判断到固定位置,欸。。。wa了5次

#include <cstdio>
#include <iostream>
#include <cmath>
#include <cstring>
using namespace std;
long long k,ansmin,ansmax,ans;
int n,m,x,y,pos;//youshang 2 zuoxia 1

void sov(){
    k-=m*n;
    long long pci,pom;
    pci = k/((n-1)*m*2);
    pom = k%((n-1)*m*2);
   // cout << "pom = "<<pom <<"pci = "<<pci <<endl;
    if(pom <= (n-1)*m && pom != 0){//shang
        ansmin = pci+1;
        ansmax =(n==2)?ansmin+1: 2*pci+2;
        if(x == n){
            ans = pci+1;
            return;
        }
        if(pom <= (n-1-x)*m +y-1){//meiyudao
            if(x==1)    ans = pci+1;
            else    ans = 2*pci+1;
        }
        else{
            if(x==1)    ans = pci+2;
           // else if(pos == 2)   ans = pci+2;
            else    ans = 2*pci+2;
        }
    }
    if(pom == 0){
       // cout << "pos = "<<pos<<endl;
        ansmin = pci+1;
        ansmax = (n==2)?ansmin:pci*2+1;
        if(x==n||x==1)    ans = pci+1;
        else    ans = 2*pci+1;
    }
    if(pom > (n-1) * m){ //xia
        ansmin = pci+1;
        ansmax = (n==2)?ansmin+1:2*pci+3;
        pom -= (n-1)*m;
        if(x == 1){
            ans = pci+2;
            return;
        }
        if(pom <= (x-2)*m+y-1){//mei
            if(x==n) {
              ans = pci+1;
            }
            else    ans = 2*pci+2;
        }
        else{
            if(x==n)
                ans = pci+2;
            else    ans = 2*pci+3;
        }
    }

}

void init(){
    scanf("%d%d%I64d%d%d",&n,&m,&k,&x,&y);
    if(n == 1){
        if(k%m!=0){
            ansmax = k/m+1;
            ansmin = ansmax-1;
            ans = (k%m>=y)?ansmax:ansmin;
        }
        else{
            ansmax = ansmin = ans=k/m;
        }
        return;
    }
    if(x == 1)    pos = 2;
    else if(x == n)   pos = 1;
    else pos = 0;
    if(k < m*n){
        ansmin = 0;
        ansmax = 1;
        if((x-1)*m+y > k)    ans = 0;
        else    ans=1;
    }
    else if(k == m*n){
        ansmin = ansmax = ans = 1;
    }
    else{
        sov();
    }
}

int main(){
    init();
    printf("%I64d %I64d %I64d\n",ansmax,ansmin,ans);
}

D题:

题意:

一个数(超过long long)可以表示为要求的进制数下,再转化为10进制。

tip:

可以知道,分成越少份越好,于是在小于n的那些就可以并到一起,贪心怎么证啊,我也不知道,反正被过掉了。。。dp的话更直观,dp【i】【j】表示前i个位置,分了j份最小值,后来发现第二维没什么用,不过我总这样

F题:

题意:

给你n l r,l到r之间找出n个数字,然后等比,问有多少

tip:

n给这么大,实际上,由于不能重复,那么25以上就没了,然后其他的,无非是上升或者下降,直接算上升,最后*2就好了,然后上升的时候有,a*p^(n-1)/q^(n-1),枚举q,根据q枚举a,首先a在l r之间,然后呢,每一位都是整数,那么a就是q^(n-1)次方的倍数了,p也靠枚举。。。gcd(p,q)等于1 ,结果l和r之间。

#include <cstdio>
#include <iostream>
#include <cstring>
using namespace std;
int n,l,r;
long long ans;
long long quickpow(int i,int n){
    long long res = 1;
    while(n > 0){
        if(n&1) res *= i;
        i *= i;
        n>>=1;
    }
    return res;
}
long long gcd(long long a,long long b){
    return b==0?a:gcd(b,a%b);
}
void sov(){
    for(int i = 1 ; i<= r; i++){
        long long t = quickpow(i,n-1);
        if(t > r)   break;
        for(int k = t ; k <= r ;k += t){
            if(k < l)   continue;
            for(int j = 1; j < i ; j++){
                if(gcd(i,j)==1){
                    long long tmp = quickpow(j,n-1);
                    if(tmp > r )  break;
                    if(k/t*tmp >= l && k/t*tmp <= r){
                        ans++;
                    }
                }
            }
        }
    }
    printf("%I64d\n",ans*2);
}

void init(){
    scanf("%d%d%d",&n,&l,&r);
    if(n == 1)  printf("%I64d\n",(long long)r-l+1);
    else if(n == 2) printf("%I64d\n",(long long)(r-l+1)*(r-l));
    else if(n >= 25)    printf("0\n");
    else{
        sov();
    }
}

int main(){
    init();
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值