2019牛客多校训练(三)

比赛链接:

https://ac.nowcoder.com/acm/contest/883#question

D. Big Integer

题意:

给出$p,n,m$

其中p为素数,求出多少个$pair(i,j),1\leq i \leq n,1\leq j \leq m$,满足下面式子

$\frac{10^{i^{j}}-1}{9}\equiv 0(mod\ p)$

分析:

ac代码:

#include<bits/stdc++.h>
#define ll long long
#define ull unsigned long long
#define pa1 pair<int,int>
#define pa2 pair<ll,int>
using namespace std;
const int maxn=1000+10;

ll phi(ll x)
{
    ll res=x;
    for(ll i=2;i*i<=x;i++){
            //cout<<x<<" "<<i<<endl;
        if(x%i==0){
            res=res/i*(i-1);
            while(x%i==0)x/=i;
        }
    }
    if(x>1)res=res/x*(x-1);
    return res;
}
ll qpow(ll x,ll y,ll mod)
{
    __int128 res=1,k=x;//因为待会mod可能为9e9
    while(y){
        if(y%2)res=res*k%mod;
        k=k*k%mod;
        y/=2;
    }
    return res;
}
vector<pa2>ve2;
ll qpow1(ll x,ll y)
{
    ll res=1;
    for(int i=1;i<=y;i++)res=res*x;
    return res;
}
int main()
{

    //cout<<qpow(2,3,3)<<endl;
    int T;
    scanf("%d",&T);
    while(T--){
        ll n,m,p;
        scanf("%lld %lld %lld",&p,&n,&m);
        if(p==2||p==5){
            printf("0\n");
            continue;
        }
        ll zz=phi(9*p),x;
        x=zz;
        for(ll i=1;i*i<=zz;i++)
            if(zz%i==0){
                if(qpow(10,i,p*9)==1)x=min(x,i);
                if(qpow(10,zz/i,p*9)==1)x=min(x,zz/i);
            }
        ll g=x;
        //以下代码寻找pair(i,j)i^j%x==0
        for(ll i=2;i*i<=g;i++){
            if(g%i==0){
                pa2 now=make_pair(i,0);
                while(g%i==0)g/=i,now.second++;
                ve2.push_back(now);
            }
        }
        if(g!=1)ve2.push_back(make_pair(g,1));

        ll ans=0;
        for(int j=1;j<=min(m,(ll)30);j++){
            ll g=1;
            for(int i=0;i<ve2.size();i++)
                g=g*qpow1(ve2[i].first,(ve2[i].second+j-1)/j);
            ll res=n/g;
            ans+=res;
            if(j==30)ans+=(m-j)*res;
        }
        printf("%lld\n",ans);
        ve2.clear();
    }
    return 0;
}

  

F. Planting Trees

题意:

 找到最大的矩形,矩形里面最大元素减最小元素不大于$m$

分析:

ac代码:

#include <bits/stdc++.h>
#define ll long long
#define pa pair<int,int>
using namespace std;
const long long INF64 = 1e18;
const int maxn=500+10;
const int maxm=405;
struct Sk{
    pa num[maxn];
    int st,en;
    void show(){
        for(int i=st;i<=en;i++){
            printf("%d ",num[i].first);
        }
        printf("\n");
    }
}sk1,sk2;
int ma[maxn][maxn];
pa lis[maxn];
int main()
{
    int T;
    scanf("%lld",&T);
    while(T--){
        int n,m,ans=0;
        scanf("%d %d",&n,&m);
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
                scanf("%d",&ma[i][j]);
        for(int up=1;up<=n;up++){
            for(int i=1;i<=n;i++)lis[i].first=lis[i].second=ma[up][i];
            for(int down=up;down<=n;down++){
                int res=0;
                for(int i=1;i<=n;i++)
                    lis[i].first=max(lis[i].first,ma[down][i]),
                    lis[i].second=min(lis[i].second,ma[down][i]);
                int l=1;
                sk1.st=sk2.st=sk1.en=sk2.en=1;
                sk1.num[1]=make_pair(lis[1].first,1);
                sk2.num[1]=make_pair(lis[1].second,1);
                for(int r=1;r<=n;r++){
                    //cout<<" lisr"<<lis[r].first<<endl;
                    while(l<r&&sk1.num[sk1.st].first-sk2.num[sk2.st].first>m){
                        l++;
                        while(sk1.num[sk1.st].second<l)sk1.st++;
                        while(sk2.num[sk2.st].second<l)sk2.st++;
                    }
//                    cout<<"-------"<<endl;
//                    sk1.show();
//                    sk2.show();
//                    cout<<"-------"<<endl;
                   // cout<<"zzz"<<l<<" "<<r<<endl;
                    if(sk1.num[sk1.st].first-sk2.num[sk2.st].first<=m)
                        res=max(res,r-l+1);
                    while(sk1.en>=sk1.st&&sk1.num[sk1.en].first<lis[r+1].first)sk1.en--;
                    sk1.num[++sk1.en]=make_pair(lis[r+1].first,r+1);
                    while(sk2.en>=sk2.st&&sk2.num[sk2.en].first>lis[r+1].second)sk2.en--;
                    sk2.num[++sk2.en]=make_pair(lis[r+1].second,r+1);
                }
                ans=max(ans,res*(down-up+1));
            }
        }
        printf("%d\n",ans);
    }
    return 0;
}

  

  

猜你喜欢

转载自www.cnblogs.com/carcar/p/11253545.html