給出乙個長度為n的陣列a。區間[l,r]的值為 ∑r−li=0a[l+i]∗a[r−i]
求所有長度為質數的區間的值的總和。
很容易想到,列舉乙個數對,然後統計他的答案
比如說,我們列舉了乙個數對(i
,j) (i,
j)
那麼他的答案的貢獻會有兩種情況 1.i
+j<=n+
1 i+j
<=n+
1這個的話,能包含他的區間長度是[j
−i+1
,j−i
+1+2
∗(i−
1)] [j−
i+1,
j−i+
1+2∗
(i−1
)]
化簡一下式子可以的得到[j
−i+1
,j+i
−1] [j−
i+1,
j+i−
1]
也就是他的答案的貢獻是a[
i]∗a
[j]∗
(s[i
+j−1
]−s[
j−i]
) a[i
]∗a[
j]∗(
s[i+
j−1]
−s[j
−i])
ss
表示質數個數的字首和
然後這個顯然可以用fft處理
然後對於i+
j>n+
1' role="presentation" style="position: relative;">i+j
>n+
1i+j
>n+
1的情況也是同理
這裡就不寫了
有乙個要注意的地方就是,你要保證(i
,j) (i,
j)
合法,也就是要讓(i
,j) (i,
j)
同奇偶
在計算的時候,我們不把2當作質數
最後單獨算就行
然後取模什麼的不用管。。
最後模就行
用double會炸精度,所以要開long double
code:
#include
#include
#include
#include
#include
using namespace std;
typedef long long ll;
typedef long double lb;
const lb pi=m_pi;
const ll mod=1e9+7;
const ll n=100005
*10;
struct qq
qq (lb _x,lb _y)
};qq operator + (qq x,qq y)
qq operator - (qq x,qq y)
qq operator * (qq x,qq y)
ll bin[n];
void fft (qq *a,ll n,ll o)}}
}ll n;
ll f[n];
ll pri[n],tot;
bool ok[n];
void prepare ()
}ok[2]=false;
for (ll u=1;u<=n;u++) f[u]=f[u-1]+ok[u];
}ll ans=0;
ll a[n];
qq b[n],c[n];
ll g[n];//儲存所有i+j=k的s[i]*s[j]
void solve ()//統計情況
int main()
51nod 1690 區間求和2
一開始考慮的是對於每個a ia i ai 有哪些a ja j aj 與它相乘,但是這樣做不了。正解是考慮每對 ai aj a i,a j ai a j 的貢獻,然後用fft優化。首先直接把長度為2 22的給算了,然後剩下的都是奇質數長度。預處理s is i si 表示1 11 i ii有多少個奇質數...
51nod 1712 區間求和
解法 這個題首先考慮乙個簡單情況 對於區間 x,y 權值為多少。容易寫出公式 f x y s y s x 1 sum y sum x 1 x 1 sum x 1 y x 1 其中s x 表示 從第乙個元素到第x個元素的 所有有序二元組的和 題目中定義的 sum表示字首和 這裡要求的是所有a x a ...
51nod1680 區間求和(BIT dp)
有n個數,給定乙個k,求所有長度大於等於k的區間中前k大數的總和。這樣就比較簡單相信大家都會,所以此題要求當k 1 n的總和,即求 n k 1 n k 1i 1 nj i k 1 區間前k大和 input 輸入五個數n,a1,a,b,c。a1表示第乙個數,a,b,c用來生成其餘n 1個數。a i a...