求 n(n<=1e12) 分解为连续整数和的方案数
非常巧妙的一道数学题
我们假设连续整数和的首项为
a
a
a ,一共有
n
n
n 项 ,和为
S
S
S
则一定满足
S
=
(
首项
+
末项
)
∗
n
2
S={(首项+末项)*n \over2}
S=2(首项+末项)∗n
化简就是
2
∗
S
=
(
2
∗
a
+
n
−
1
)
∗
n
2*S=(2*a+n-1)*n
2∗S=(2∗a+n−1)∗n
显然有两个未知数
a
a
a 和
n
n
n
如果我们枚举
a
a
a 和
n
n
n 一定会爆掉
1.分析
n
n
n 的范围:
n 是项数,当
a
=
1
a=1
a=1时
n
n
n 最大 这时
2
∗
S
=
(
n
+
1
)
∗
n
2*S=(n+1)*n
2∗S=(n+1)∗n
所以我们可以得到
n
∗
n
<
(
n
+
1
)
∗
n
=
2
∗
S
n*n<(n+1)*n=2*S
n∗n<(n+1)∗n=2∗S
所以
n
<
s
q
r
t
(
2
∗
S
)
n
2.分析
a
a
a 的范围:
而首项显然我们可以取到
a
2
a\over2
2a 所以枚举两个值显然不合适
最大为2e11
分析完复杂度后我们明显的可以看出要从
n
n
n下手,枚举所有的
n
n
n ,判断此时的首项是否合法即可
首项要是个正整数
#include
using namespace std;
#define fi first
#define se second
#define IOS std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
typedef long long ll;
const int N = 2e5+10;
const int NN = 1e6+10;
const int pp = 1e9+7;
typedef pair<int,int>PII;
ll n,ans;
int main()
{
cin>>n;
for(ll i=2;i<=sqrt(n*2);i++)
{
ll k=((n*2)-i*i+i)%(i*2);
if(k==0&&((n*2)-i*i+i)/(i*2)>0) ans++;
}
cout<<ans;
return 0;
}
给出 N 个数,求满足下面式子的 l ,r 有多少组
∑
i
=
l
r
A
i
=
k
\displaystyle\sum_{i=l}^rA_i=k
i=l∑rAi=k
我们可以用前缀和优化一下,优化完了之后就是求满足
s
u
m
[
r
]
−
s
u
m
[
l
−
1
]
=
k
sum[r]-sum[l-1]=k
sum[r]−sum[l−1]=k的 l , r 有多少组
这个题就变成了典型的
A
−
B
=
k
A-B=k
A−B=k 问题;我们可以边存边计算,我们处理的每个数都是一个
A
A
A,贡献就是前面数里
B
B
B 的数量 也就是
A
−
K
A-K
A−K 的数量
#include
using namespace std;
#define fi first
#define se second
#define IOS std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
typedef long long ll;
const int N = 2e5+10;
const int NN = 1e6+10;
const int pp = 1e9+7;
typedef pair<int,int>PII;
ll sum[N];
ll n,k,t,ans;
map<ll,ll>mp;
int main()
{
cin>>n>>k;
for(int i=1;i<=n;i++)
{
cin>>t;
sum[i]=sum[i-1]+t;
}
mp[0]=1;
for(int i=1;i<=n;i++)
{
ans+=mp[sum[i]-k];
mp[sum[i]]++;
// cout<
}
cout<<ans;
return 0;
}