签到,只要有k就行
#include
using namespace std;
const int N = 3e5 + 5;
typedef long long ll;
typedef pair<ll, ll> pll;
typedef array<ll, 3> p3;
int mod = 998244353;
const int maxv = 4e6 + 5;
void solve()
{
int n,c;
cin>>n>>c;
vector<int> a(n+5);
for(int i=1;i<=n;i++) cin>>a[i];
for(int i=1;i<=n;i++){
if(a[i]==c) {
cout<<"YES"<<endl;
return ;
}
}
cout<<"NO"<<endl;
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
int t;
t = 1;
cin>>t;
while (t--)
{
solve();
}
system("pause");
return 0;
}
思路:按照奇数序列构造即可,即 1 , 3 , 5 ⋯ n ∗ 2 − 1 1,3,5 \cdots n*2-1 1,3,5⋯n∗2−1这种构造方法。
证明:因为所有数都是奇数,对于 a i , a i + 1 , a i + 2 a_i,a_{i+1},a_{i+2} ai,ai+1,ai+2而言, a i + a i + 1 a_i+a_{i+1} ai+ai+1为偶数, a i + 2 × 3 a_{i+2}\times3 ai+2×3依旧为奇数,偶数不能被奇数整除,原式得证。
#include
using namespace std;
const int N = 3e5 + 5;
typedef long long ll;
typedef pair<ll, ll> pll;
typedef array<ll, 3> p3;
int mod = 998244353;
const int maxv = 4e6 + 5;
void solve()
{
int n;
cin>>n;
for(int i=1;i<=n;i++){
cout<<i*2-1<<" ";
}
cout<<endl;
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
int t;
t = 1;
cin>>t;
while (t--)
{
solve();
}
system("pause");
return 0;
}
思路:若给定的 x x x小于前 k k k个或者大于后 k k k个,那么则一定不合法。否则一定可以通过相关替换拼凑出该数。
#include
using namespace std;
const int N = 3e5 + 5;
typedef long long ll;
typedef pair<ll, ll> pll;
typedef array<ll, 3> p3;
int mod = 998244353;
const int maxv = 4e6 + 5;
void solve()
{
ll n,k,x;
cin>>n>>k>>x;
ll c1=(1+k)*k/2;
if(x<c1){
cout<<"NO"<<endl;
return ;
}
ll c2=(n-k+1+n)*k/2;
if(x>c2){
cout<<"NO"<<endl;
return ;
}
cout<<"YES"<<endl;
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
int t;
t = 1;
cin>>t;
while (t--)
{
solve();
}
system("pause");
return 0;
}
思路:我们可以发现,所有区间都是不相交的,每次进行的翻转操作,即是对于 [ l , r ] [l,r] [l,r]的区间,以 x x x为边界,以区间中心为对称轴进行翻转。所以具体怎么翻转我们并不关系,我们只用记录每个点的翻转次数即可。
#include
using namespace std;
const int N = 1e6 + 5;
typedef long long ll;
typedef pair<ll, ll> pll;
typedef array<ll, 3> p3;
int mod = 1e9+7;
const int maxv = 4e6 + 5;
void solve()
{
int n,k;
cin>>n>>k;
string s;
cin>>s;
vector<int> a(k+5),b(k+5),d(n+5);
for(int i=1;i<=k;i++) cin>>a[i];
for(int i=1;i<=k;i++) cin>>b[i];
s=" "+s;
int q;
cin>>q;
for(int i=1;i<=q;i++){
int x;
cin>>x;
int loc=(lower_bound(b.begin()+1,b.begin()+k+1,x)-b.begin());//用二分去找x所在的区间
int l=min(x,a[loc]+b[loc]-x);
int r=max(x,a[loc]+b[loc]-x);
d[l]++,d[r+1]--;//进行差分
}
for(int i=1;i<=n;i++) d[i]+=d[i-1];
for(int i=1;i<=k;i++){
int l=a[i],r=b[i];//对给定的k个区间进行遍历
for(int j=l;j<=(l+r)/2;j++){//因为翻转前半部分和后半部分是等价的,所以只用计算前半部分
if(d[j]%2){//如果当前点的翻转次数为奇数次
swap(s[j],s[r-(j-l)]);
}
}
}
for(int i=1;i<=n;i++) cout<<s[i];
cout<<endl;
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
int t;
t=1;
cin>>t;
while(t--){
solve();
}
system("pause");
return 0;
}
思路:st表维护区间与,因为与运算只会越与越小,所以可以用二分去维护能到达的最右端点。对于区间的维护,不一定需要使用st表,线段树,前缀和均可。
#include
using namespace std;
const int N = 2e5 + 5;
typedef long long ll;
typedef pair<ll, ll> pll;
typedef array<ll, 3> p3;
int mod = 998244353;
const int maxv = 4e6 + 5;
int f[N][30];
int query(int l,int r)
{
int len=__lg(r-l+1);
int ans=f[l][len]&f[r-(1<<len)+1][len];
return ans;
}
void st()
{
int n,q;
cin>>n;
vector<int> a(n+5);
for(int i=1;i<=n;i++){
int x;
cin>>x;
a[i]=x;
f[i][0]=x;
}
for(int j=1;j<=25;j++){
for(int i=1;i+(1<<j)-1<=n;i++){
f[i][j]=f[i][j-1]&f[i+(1<<(j-1))][j-1];
}
}
cin>>q;
for(int i=1;i<=q;i++){
int l,k;
cin>>l>>k;
if(a[l] < k)
{
cout << -1 << ' ';
continue;
}
int L = l, R = n;
int ans=0;
while(L<=R){
int mid=(L+R)/2;
int res=query(l,mid);
if(res>=k) {
ans=mid;
L=mid+1;
}
else R=mid-1;
}
cout<<ans<<" ";
}
cout<<endl;
}
void solve()
{
st();
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
int t;
t = 1;
cin>>t;
while (t--)
{
solve();
}
system("pause");
return 0;
}
思路:
当且仅当 d ( n ) d(n) d(n)除以 n n n时才存在解。
证明:考虑数 n = p 1 α 1 ⋅ p 2 α 2 ⋯ p k α k n = p_1^{\alpha_1} \cdot p_2^{\alpha_2} \cdots p_k^{\alpha_k} n=p1α1⋅p2α2⋯pkαk的质因数分解,其中 p i p_i pi表示 i i ith质数, α i \alpha_i αi表示 i i ith质数的最高幂,使得 p i α i p_i^{\alpha_i} piαi除以 n n n。知道了这一点,我们就可以用下面的公式计算出 n n n的被除数: d ( n ) = ( α 1 + 1 ) ⋅ ( α 2 + 1 ) ⋯ ( α k + 1 ) d(n) = (\alpha_1+1) \cdot (\alpha_2+1) \cdots (\alpha_k+1) d(n)=(α1+1)⋅(α2+1)⋯(αk+1).
现在让我们考虑一下我们正在进行的运算。我们正在用数字 n n n 乘以一个与 n n n 没有公共质因数的数字 a a a (条件 g c d ( a , n ) = 1 gcd(a, n) = 1 gcd(a,n)=1)。(条件 g c d ( a , n ) = 1 gcd(a, n) = 1 gcd(a,n)=1)。
n n n乘以任何与 n n n没有公共质因数的数字都只会给 n n n带来新的质因数,因此, d ( n ) d(n) d(n) 永远是数字 d ( n ⋅ a ) d(n\cdot a) d(n⋅a) 的被除数。因此,我们可以写出 d ( n ⋅ a ) = v ⋅ d ( n ) d(n \cdot a) = v \cdot d(n) d(n⋅a)=v⋅d(n)。任选一个不是 n n n 因数的素数 p p p(这样的素数是存在的,因为素数的个数是无限的,而 n n n 的素数因数是有限的)。用 n n n乘以 a = p k − 1 a = p^{k-1} a=pk−1,得到 d ( n ⋅ a ) = d ( n ) ⋅ k = n d(n\cdot a) = d(n) \cdot k = n d(n⋅a)=d(n)⋅k=n。
我们可以预处理出每个小于 1 0 6 10^6 106 的正整数的最小质因数。这样,我们就能在对数时间内对所有小于或等于 1 0 6 10^6 106的数字进行因式分解。我们还利用上述公式对 n n n进行因式分解并找出其除数个数,然后为每个质因数存储其仍能整除 n n n的最高幂次。我们都把这个结构称为 p o w e r power power。
现在我们需要处理查询:
对于类型 2 的查询,我们只需重置所有内容。
对于第一个查询,我们在 O ( log x ) \mathcal{O}(\log{x}) O(logx) 运算中对 x x x 进行因式分解,并让 x = r 1 β 1 ⋅ r 2 β 2 ⋯ r ℓ β ℓ x = r_1^{\beta_1} \cdot r_2^{\beta_2} \cdots r_\ell^{\beta_\ell} x=r1β1⋅r2β2⋯rℓβℓ 成为数字 x x x 的因式分解。我们通过以下操作更新 d ( n ) d(n) d(n):对于 x x x中的每个素数 r i r_i ri,用 d ( n ) d(n) d(n)除以 p o w e r [ r i ] + 1 power[r_i]+1 power[ri]+1,然后将 β i \beta_i βi加到 p o w e r [ r i ] power[r_i] power[ri],再用 d ( n ) d(n) d(n)乘以 p o w e r [ r i ] + 1 power[r_i]+1 power[ri]+1。计算出 d ( n ) d(n) d(n)后,我们应该检查 n n n是否能被它整除。我们可以用两种方法来做这件事:
因为 d ( n ) d(n) d(n)不会超过 1 0 9 10^9 109,但是 n n n的范围会很大很大,我们无法使用long long类型存下,我们考虑换一种存法,即对 n n n进行质因数分解,用 n = r 1 β 1 ⋅ r 2 β 2 ⋯ r ℓ β ℓ n = r_1^{\beta_1} \cdot r_2^{\beta_2} \cdots r_\ell^{\beta_\ell} n=r1β1⋅r2β2⋯rℓβℓ这种形式储存,具体使用map或者vector进行维护都可以。
对于检查是否能被 n n n整除,对于我们计算出的每一个值 m u l mul mul,我们让这个值去对 n n n的所有质因子进行遍历,若最终能够变成1,那么就代表肯定能够整除,因为 n n n若是能够整除 m u l mul mul,那么代表n的每一个质因子的个数肯定是大于等于 m u l mul mul质因子的个数的,只要最终 m u l mul mul能变为 1 (注,此时不一定需要把 n n n的因子全部耗尽),那么肯定合法。
#include
using namespace std;
const int N = 2e5 + 5;
typedef long long ll;
typedef pair<ll, ll> pll;
typedef array<ll, 3> p3;
int mod = 998244353;
const int maxv = 4e6 + 5;
const int MAX = 1e6;
int f[MAX+5];
int prime[MAX+5];
int st[MAX+5];
int cnt=0;
void ol()//欧拉筛预处理每个数的最小因子
{
int i,j;
for(i=2;i<=MAX;i++){
if(!st[i]){
prime[cnt++]=i;
f[i]=i;
}
for(j=0;i*prime[j]<=MAX&&j<cnt;j++){
st[i*prime[j]]=1;
f[i*prime[j]]=prime[j];
if(i%prime[j]==0){
break;
}
}
}
}
void solve()
{
int n,q;
cin>>n>>q;
ll mul=1;
map<int,int> mp;
while(n>1){
int p=f[n];
while(n%p==0){
mp[p]++;
n/=p;
}
}
for(auto [x,y]: mp){
mul*=(y+1);
}
ll tar=mul;//记录一开始n的因子个数值
auto init=mp;//记录一开始n的因子信息
while(q--){
int op;
cin>>op;
if(op==1){
int x;
cin>>x;
//vector c=factor_small(x);
while(x>1){//对于每一个x,在logx的时间复杂度内处理出其所有因子
int p=f[x];
if(x%p==0){
mul/=(mp[p]+1);
while(x%p==0){
mp[p]++;
x/=p;
}
mul*=(mp[p]+1);
}
}
ll c=mul;
for(auto [a,b]: mp){//检验是否整除
while(c%a==0&&b>0) {
c/=a;
b--;
}
}
if(c==1) cout<<"YES"<<endl;
else cout<<"NO"<<endl;
}
else{
mul=tar;
mp=init;
}
}
cout<<endl;
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
int t;
t = 1;
cin>>t;
ol();
while (t--)
{
solve();
}
system("pause");
return 0;
}