【一】n的约数
题解:
2)然后很容易发现一个规律:如果两个数的约数个数相同,那么指数大小按递减顺序排列的话所获得的数更小。
举个例子:
6个约数:
12
=
2
2
∗
3
,
18
=
2
∗
3
2
12=2^2 *3, 18=2 * 3^2
12=22∗3,18=2∗32
24个约数:
360
=
2
3
∗
3
2
∗
5
,
540
=
2
2
∗
3
3
∗
5
360=2^3 *3^2 *5, 540=2^2 * 3^3 *5
360=23∗32∗5,540=22∗33∗5
因为我们关注的就是寻找最大数目的约数,所以不需要考虑这个满足条件的数字具体是什么,所以直接考虑如何构造约数,使得原数字尽量小,然后判断这个数字是否处于题目给定范围内的,如果处于那么这个约数的数目是存在的,如果不处于,那么就不存在。
#include<bits/stdc++.h>
#define mp make_pair
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, int> pli;
typedef pair<ll, ll> pll;
typedef long double ld;
const int N=1e7+10;
const int MAXN=20010;
const int INF=0x3f3f3f3f;
const double eps=0.0000001;
const ll mod=1e9+7;
int a[20]={0,2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,51};
ll ans,m,n,x,maxn;
void dfs(ll val,ll pre,ll num,ll flo)//val当前值,pre当前的素数,num约数的个数,flo指数上限
{
if(num>maxn||num==maxn&&ans>val)
{
maxn=num;
ans=val;
}
ll z=1,gcd,now=val;
while(z<=flo)
{
z++;
if(x/a[pre]<now) break;
now=now*a[pre];
gcd=z*num;
dfs(now,pre+1,gcd,z-1);//指数递减,此次是z,下一次的上限为z-1
}
}
int main()
{
ll t;
scanf("%lld",&t);
while(t--)
{
scanf("%lld",&x);
maxn=-1,ans=-1;
dfs(1,1,1,16);
printf("%lld\n",maxn);
}
//cout << "Hello world!" << endl;
return 0;
}
华华送奕奕小礼物
题解:
设
s
u
m
a
sum_a
suma为
a
a
a的前缀和,
s
u
m
b
sum_b
sumb为
b
b
b的前缀和。
则以
(
x
1
,
y
1
)
(x1,y1)
(x1,y1)为左上角,以
(
x
2
,
y
2
)
(x2,y2)
(x2,y2)为右下角的矩阵的权值为
(
s
u
m
a
[
x
2
]
−
s
u
m
a
[
x
1
−
1
]
)
∗
(
s
u
m
b
[
y
2
]
−
s
u
m
b
[
y
1
−
1
]
)
(sum_a[x2]-sum_a[x1-1])* (sum_b[y2]-sum_b[y1-1])
(suma[x2]−suma[x1−1])∗(sumb[y2]−sumb[y1−1])
其中要满足
x
1
<
=
x
2
,
y
1
<
=
y
2
x1<=x2,y1<=y2
x1<=x2,y1<=y2。
x
1
,
x
2
x1,x2
x1,x2的选择与
y
1
,
y
2
y1,y2
y1,y2的选择相互独立。
可以预处理所有
y
1
,
y
2
y1,y2
y1,y2的组合,然后排序。接下来枚举
x
1
,
x
2
,
x1,x2,
x1,x2,对
y
y
y二分即可。
复杂度
n
2
∗
l
o
g
(
m
2
)
n ^2*log(m ^2)
n2∗log(m2)
#include<bits/stdc++.h>
#define mp make_pair
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, int> pli;
typedef pair<ll, ll> pll;
typedef long double ld;
const int N=1e7+10;
const int MAXN=20010;
const int INF=0x3f3f3f3f;
const double eps=0.0000001;
const ll mod=1e9+7;
ll n,m,l,r,x,cnt;
ll a[N],b[N],c[N];
ll slove(ll x)
{
ll ans=0;
ll l=0,r=cnt-1;
while(l<=r)
{
ll mid=(l+r)/2;
if(c[mid]<=x)
{
ans=mid+1,l=mid+1;
}
else
r=mid-1;
}
return ans;
}
ll work(ll x)
{
ll ans=0;
for(int i=1;i<=n;i++)
{
for(int j=0;j<i;j++)
{
ans+=slove(x/(a[i]-a[j]));
}
}
return ans;
}
int main()
{
scanf("%lld%lld%lld%lld",&n,&m,&l,&r);
for(int i=1;i<=n;i++)
{
scanf("%lld",&x);
a[i]=a[i-1]+x;
}
for(int i=1;i<=m;i++)
{
scanf("%lld",&x);
b[i]=b[i-1]+x;
for(int j=0;j<i;j++)
{
c[cnt++]=b[i]-b[j];
}
}
sort(c,c+cnt);
printf("%lld\n",work(r)-work(l-1));
}
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int mod=1e9+7;
ll pow1(ll a,ll b)
{
ll r=1;
while(b)
{
if(b&1)
r=r*a%mod;
a=a*a%mod;
b/=2;
}
return r;
}
int main()
{
int n,m,k,a,b;
scanf("%d%d%d%d%d",&n,&m,&k,&a,&b);
ll p=1LL*a*pow1(b,mod-2)%mod;
ll s=1LL*(n+m)*pow1(n+m+1,mod-2)%mod;
ll ans=1LL*n*pow1(s,k)%mod+p*(s-pow1(s,k+1))%mod*pow1(1-s,mod-2)%mod;
ans=ans%mod+mod;
printf("%lld\n",ans%mod);
return 0;
}
#include<bits/stdc++.h>
#define mp make_pair
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, int> pli;
typedef pair<ll, ll> pll;
typedef long double ld;
const int N=1e7+10;
const int maxn=1e5+10;
const int INF=0x3f3f3f3f;
const double eps=0.0000001;
const ll mod=1e9+7;
int n;
ll C,W;
ll a[maxn],b[maxn];
int num[maxn],tx_num[maxn],id[maxn];///num表示循环次数,tx-num表示副本,id维护第几秒
struct note
{
ll cost,id;
};
bool operator<(const note &A,const note &B)
{
return A.cost>B.cost;
}
priority_queue<note>q;
bool slove(ll x)
{
for(int i=1;i<=min(x,(ll)n);i++)
{
note e;
e.cost=a[i]*b[1];
num[i]=x/n;
if(x%n&&i<=x%n)
{
num[i]++;
}
tx_num[i]=num[i];
e.id=i;
id[i]=1;
q.push(e);
}
ll c=C,w=W;
while(c)
{
note fir=q.top();
c--;
w-=fir.cost;
if(w<=0) return 0;
num[fir.id]--;
if(num[fir.id]==0)
{
id[fir.id]++;
num[fir.id]=tx_num[fir.id];
fir.cost=a[fir.id]*b[id[fir.id]];
q.pop();
q.push(fir);
}
}
while(!q.empty())
q.pop();
return 1;
}
int main()
{
scanf("%d%lld%lld",&n,&C,&W);
for(int i=1;i<=n;i++)
scanf("%lld",&a[i]);
for(int i=1;i<=C;i++)
scanf("%lld",&b[i]);
ll l=1,r=n*C,ans=INF;
while(l<=r)
{
ll mid=(l+r)>>1;
if(slove(mid))
{
ans=mid;
r=mid-1;
}
else
{
l=mid+1;
}
}
if(ans==INF) printf("-1\n");
else
printf("%lld\n",ans);
}
华华和奕奕学物理
题解:树状数组+公式推导
大佬的详细题解
比较有意思的就是,找到速度小的所有球都是谁,一开始想法很朴素就查询一次然后比较一次,没有想到更好的方法。然后答案给的思路就很优秀了,因为是在线查询所以,查询的肯定为之前抛下去的小球。
所以就可以这样想,已知若某一时刻a球比b球速度快,则a球始终比b球速度快,所以想判断某一时刻的速度大小和判断随机时刻的速度大小没有区别,所以直接撸到底, 在最后时刻时将所有0-V的动能求个和就好了。
所以可以用最终速度V代表数组的下标,那么数组如何维护动能呢,
因为动能仅与查询的时间 t2 相关且二次相关,其余的都是常数,所以公式有三项,也就是可以用V的数组,分别维护三个系数就好了。最后区间求和就可以用各种数据结构维护一下。
#include<bits/stdc++.h>
using namespace std;
const int maxn=4e6+100;
const int T=3e5+10;
const int mod=1e9+7;
const int g=10;
#define ll long long
ll bit[8][maxn];
void add(ll b[],int i,ll C)
{
while(i<maxn)
{
b[i]=(b[i]+C)%mod;
i+=i&-i;
}
}
ll sum(ll b[],int i)
{
ll ans=0;
while(i>0)
{
ans+=b[i];
i-=i&-i;
}
return ans%mod;
}
int main()
{
int Q;scanf("%d",&Q);
while(Q--)
{
int op,v,t,m;scanf("%d%d%d",&op,&v,&t);
if(op==1)
{
int V=v+g*(T-t);
scanf("%d",&m);
add(bit[1],V,1LL*m*v%mod*v%mod);
add(bit[2],V,1LL*m*g*g%mod);
add(bit[3],V,1LL*m*g*g%mod*t%mod*t%mod);
add(bit[4],V,1LL*2*m*g*g%mod*t%mod);
add(bit[5],V,1LL*2*m*v%mod*g%mod);
add(bit[6],V,1LL*2*m*v%mod*g*t%mod);
}
else
{
int V=min(v+g*(T-t),maxn-1);
ll ans=0;
ans+=sum(bit[1],V);
ans+=sum(bit[2],V)*t%mod*t%mod;
ans+=sum(bit[3],V);
ans-=sum(bit[4],V)*t%mod;
ans+=sum(bit[5],V)*t%mod;
ans-=sum(bit[6],V);
ans%=mod;
if(ans<0)
ans+=mod;
printf("%lld\n",ans);
}
}
return 0;
}