CF1920题解
C.Partitioning the Array
题意:
给定长度为n的数组,将其分为k份,模一个数m后,每一份相等
思路: 枚举n的因子,然后对于每个相同的位置求gcd,gcd不等于1则计数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include <bits/stdc++.h>
using namespace std;
void solve(){
int n;
cin >> n;
int A[n];
for (int &i : A)
cin >> i;
int ans = 0;
for (int k = 1; k <= n; k++){
if (n % k == 0){
int g = 0;
for (int i = 0; i + k < n; i++)
g = __gcd(g, abs(A[i + k] - A[i]));
ans += (g != 1);
}
}
cout<<ans<<"\n";
}
int main(){
ios_base::sync_with_stdio(0); cin.tie(0);
int tc;
cin >> tc;
while (tc--)
solve();
}
D.Array Repetition
题意:
有两个操作:
操作1:1 x
将x加入数组后方
操作2:2 x
将目前数组赋值x次加到后方
若干次操作后,给定询问q,输出当前位置的数字 思路:
二分,创建a,b两个数组一个放数,一个放总数(操作2放的数记为-1),每次二分比x
更大的数量的位置
- 若
b[l]=x
说明为最后一个数,直接从后往前找第一个不是-1
的数 - 否则,若
a[l]=-1
说明数在当前循环中,x%=b[l-1]
,如果为0
则说明在当前末尾,找出第一个数即可;否则继续二分 - 若
a[l]!=-1
,若a[l-1]=-1
说明在当前末尾找第一个数,否则即为当前数1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61
void solve(){ int n,q; cin>>n>>q; vector<ll> a,b; ll num=0; while(n--){ int op; ll x; cin>>op>>x; if(op==1)a.push_back(x),b.push_back(++num); else{ if((__int128)num*(x+1)>1e18)num=1e18,num++; else num*=(x+1); a.push_back(-1),b.push_back(num); } } while(q--){ ll x; cin>>x; while(1){ int l=0,r=a.size()-1; while(l<r){ int mid=l+r>>1; if(b[mid]>x)r=mid; else l=mid+1; } if(b[l]==x){ if(a[l]!=-1)cout<<a[l]<<" "; else{ while(a[l]==-1)l--; cout<<a[l]<<" "; } break; } else{ if(a[l]==-1){ x%=b[l-1]; l--; if(x==0){ while(a[l]==-1)l--; cout<<a[l]<<" "; break; } } else{ l--; if(a[l]==-1){ while(a[l]==-1)l--; cout<<a[l]<<" "; break; } else{ cout<<a[l]<<" "; break; } } } } } cout<<"\n"; }
E.Counting Binary Strings
题意:
找出符合下列性质的01串个数, - 有
n
个子串满足只有一个1
- 这样的子串长度最多为
k
思路:
对于一个1
来说,若左边有n
个0
,右边有m
个0
,则满足第一条性质的串为(n+1)*(m+1)
个
因为满足第二条性质,所以n+m+1<=k
即(n+1)*(m+1)<=k+1
拓展到多个1
用数组 $ a_1,a_2,a_3,…$ 表示被1
间隔开的0
的各个区间长度
则 $ sum=a_1 \cdot a_2 + a_2 \cdot a_3+…+ $
考虑dp
$dp_{i,j}=\sum_{p=1}^{min(\frac{i}{j},k+1-j)}dp_{i-j \cdot p,p} $
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
void solve(){
int n,k;
cin>>n>>k;
vector<vector<int>> dp(n+1,vector<int>(n+1));
for(int i=1;i<=n;i++)dp[0][i]=1;
for(int i=1;i<=n;i++){
for(int j=1;j<=i;j++){
for(int p=1;p*j<=i&&p+j<=k+1;p++){
dp[i][j]=(dp[i][j]+dp[i-p*j][p])%mod;
}
}
}
int ans=0;
for(int i=1;i<=n;i++)ans=(ans+dp[n][i])%mod;
cout<<ans<<"\n";
}
This post is licensed under CC BY 4.0 by the author.