比赛链接:
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;
}