牛客小白月赛5题解

前情提要:
B题的结论到目前为止还没能推出来。
赛时七题,赛后补了C、E。

A 无关(relationship)

容斥原理dfs实现,注意剪枝否则爆long long

#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;
#define LL unsigned long long
const int maxn = 1e2+3;
LL l,r,k;
LL a[maxn];

LL sum=0;
void dfs(LL x,LL now,LL c)
{
    if(x>r) return;
    if(c&1){
        sum+=r/x-(l-1)/x;
    }else{
        sum-=r/x-(l-1)/x;
    }
    for(LL i=now+1;i<=k;i++){
        dfs(x*a[i],i,c+1);
    }
}

int main()
{

    while(~scanf("%llu%llu%llu",&l,&r,&k)){
        sum=0;
        for(LL i=1;i<=k;i++)
            scanf("%llu",&a[i]);
        for(LL i=1;i<=k;i++)
            dfs(a[i],i,1);
        printf("%llu\n",(r-l+1)-sum);
    }
}

B 范围(range)

还待解决,往大佬们不吝赐教。

#include 
using namespace std;
int main() {

    double A, B;
    scanf("%lf%lf", &A, &B);
    double L = (A - sqrt(2 * B - A * A)) / 2, R = (A + sqrt(2 * B - A * A)) / 2;
    printf("%.2f %.2f", L, R);

}

C 水题(water)

分类讨论。
1.事前打表求出13之内的N皇后解。
2. f(i) f ( i ) 呈现斐波纳挈规律,所以可以打表查看x是否为斐波纳挈数。至于0的个数,可以通过对m分解质因数,然后枚举质因数的i次幂解决。

#include 
using namespace std;
#define ll long long int
#define clr(x,y) memset(x,y,sizeof x)
const ll INF = 1e18;

int ans[15]= {0,1,0,0,2,10,4,40,92,352,724,2680,14200,73712,365596};
int pri[25]= { 2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97};
ll f[100];
ll cnt[100];
ll num[100];
void init();
int main()
{
    clr(cnt,0);clr(num,0);
    init();
    ll x,m;
    scanf("%lld %lld",&x,&m);
    bool flag=0;
    for(int i=1;i<=89;i++){
        if(f[i]>x) break;
        if(x==f[i]){
            flag=1;break;
        }
    }
    if(flag==1){
        ll ans=INF;
        int cs=0;
        ll tmp=m;
        for(int i=0;i<25;i++){
            if(tmp==1) break;
            if(tmp%pri[i]==0){
                cnt[++cs]=pri[i];
                while(tmp%pri[i]==0){
                    tmp/=pri[i];
                    num[cs]++;
                }
            }
        }
        if(tmp>1){
            cnt[++cs]=tmp;
            num[cs]++;
        }
        for(int i=1;i<=cs;i++){
            tmp=0;
            for(ll j=cnt[i];j<=x;j*=cnt[i])
                tmp+=x/j;
            ans=min(ans,tmp/num[i]);
        }
        printf("%lld\n",ans);

    }
    else{
        ll z=x%(min(1ll*13,m))+1;
        printf("%d\n",ans[z]);
    }
    return 0;
}
void init(){

    f[1]=1;
    f[2]=1;
    for(int i=3;i<=99;i++){
        f[i]=f[i-1]+f[i-2];
        if(f[i]>=INF) break;
    }

}

D 阶乘(factorial)

在单个阶乘内求末尾0的个数的基础上多了更多的考虑。突破口依然一样,盯住贡献量。

#include
using namespace std;
#define ll long long int
const int maxn=1e6+2333;
int main()
{   ll n;
    scanf("%lld",&n);
    if(n<=4) {
        printf("0\n");
        return 0;
    }
    ll ans=0, cnt=0;
    ll tmp=0;int i;
    for(i=5;i<=n;i+=5){
        cnt++;
        ll k=0;tmp=i;
        while(tmp%5==0){
            tmp/=5;
            k++;
        }
        ans+=(n-i+1)*k;
    }
    printf("%lld\n",ans);
    return 0;
}

E 面积(area)

题如其名,的确是面积问题。
点阵的最大生成图面积需要和三角形面积相等才可以剪裁拼接得到。
三角形面积:可以通过向量叉积求得;
点阵:通过观察每多一行或每多一列的图形变换,可以得到点阵的面积规律。

#include 
using namespace std;

int main(){
    std::ios::sync_with_stdio(false);
    long long n,m,x1,x2,y1,y2;
    double s1,s2;
    while(cin>>n>>m){
        cin>>x1>>y1>>x2>>y2;
        s1=1.0*n/2.0*m-1;
        s2=abs(x1*y2-x2*y1)/2.0;
        if(s1==s2) cout<<"Yes\n";
        else cout<<"No\n";
    }
    return 0;
}

F 圆(circle)

python秒?骗人的吧QAQ
查公式网站找到的规律ORZ

#include 
#include 
#include 
using namespace std;
typedef long long int LL;

int main() {

    LL n;
    while(scanf("%lld",&n)!=EOF) {

        printf("%lld\n",1+n*(n-1)/2+n*(n-1)*(n-2)*(n-3)/24);
    }
    return 0;
}

G 异或(xor)

直接看样例解释可以得到答案。
每三个数,前两个数是奇数,后一个是偶数。偶数不能吃。

#include
#include
using namespace std;


#define ll long long


int main()
{
   ll n;
   while(~scanf("%lld",&n)){
    if(n%3==0){
        printf("%lld\n",(n/3)*2);
    }
    else if(n%3==1){
          printf("%lld\n",(n/3)*2+1);
    }
    else{
         printf("%lld\n",(n/3)*2+2);
    }
   }
   return 0;
}

H 最大公约数(lcm)

就是单纯的求最大公约数,注意要先除gcd再乘,否则爆炸。

#include

using namespace std;
const int maxn=1e5+45;
#define INF 0x3f3f3f3f;
#define ll unsigned long long
#define charmax(x,y) x=max(x,y)
#define charmin(x,y) x=min(x,y)
#define clr(x,p) memset(x,p,sizeof x)
ll gcd(ll a,ll b){
    return b==0?a:gcd(b,a%b);
}
int main()
{
    ll a,b;
    cin>>a>>b;
    b=b/gcd(a,b);
    cout<return 0;
}

I 区间 (interval)

线段树MLE;注意q的取值是0和非0而不是0和1;
因为只有一次查询,可以离线操作,和刚学树状数组遇到的气球染色问题类似。

#include
using namespace std;
#define ll long long int
const int maxn=1e6+2333;
int a[maxn];
int q[maxn];
int v[maxn];
int u[maxn];
int c[maxn];
int main(){
    int n,m;
    scanf("%d %d",&n,&m);
    for(int i=1;i<=n;i++){
        scanf("%d",&a[i]);
    }
    ll ans=0;
    ll tmp=0;

    int L,R;
    for(int i=1;i<=m;i++)
    {scanf("%d %d %d %d",&q[i],&u[i],&v[i],&c[i]);}
    scanf("%d %d",&L,&R);
    for(int i=L;i<=R;i++){
        ans+=1ll*a[i];
    }
   // cout<for(int i=1;i<=m;i++){
        tmp=0;
        if(v[i]R) continue;
        if(u[i]<=L){
            if(v[i]>=R) tmp+=R-L+1;
            else {
                tmp+=v[i]-L+1;
            }
        }
        else{
            if(v[i]<=R) tmp+=v[i]-u[i]+1;
            else{
                tmp+=R-u[i]+1;
            }
        }
        if(q[i]!=1) tmp=tmp*c[i];
        else tmp=tmp*(-c[i]);
        ans+=tmp;
    }
    printf("%lld\n",ans);


    return 0;
}

J 时间(time)

这个题写法应该挺多的,我是打表二分找答案输出。

#include
using namespace std;


#define ll long long
const int maxn=1e5+20;
int a[maxn];
int ans[maxn];int x[maxn];int y[maxn];
int c[5];
int main()
{
    int a,b;
    char s;
    cin>>a>>s>>b;int sz=0;
    for(int i=0,j=0;;i++){
        if(j>=24) break;
        if(i==60) {
            i=0;j++;
        }
        c[2]=j%10;c[1]=j/10;
        c[3]=i/10;c[4]=i%10;
        if(c[1]==c[4]&&c[2]==c[3]){
                ans[++sz]=j*100+i;
                x[sz]=j;y[sz]=i;
        }
    }
    int p=a*100+b;
    int pos=lower_bound(ans+1,ans+1+sz,p)-ans;
    if(p&&p<=ans[pos]){
        printf("%d:%d\n",x[pos-1],y[pos-1]);
    }
    else printf("%d:%d\n",x[sz],y[sz]);
    pos=upper_bound(ans+1,ans+1+sz,p)-ans;
    if(pos<=sz){
        printf("%d:%d\n",x[pos],y[pos]);
    }
    else{
        printf("%d:%d\n",x[1],y[1]);
    }
   return 0;
}

你可能感兴趣的:(Contest)