a.Haitang and Game
题意:
给定一个集合,dXqwq和Haitang轮流在选集合选x,y,假如gcd(x,y)不在集合内,可以插入gcd(x,y)。
不能操作者输。
题解:
注意数据范围小,只有1e5. 枚举每个数x的倍数,假如这个数存在的倍数的gcd等于x,那这个数就可以进行一次操作。
我们就知道一共可以操作多少次,结果就清楚了
代码:
#include<bits/stdc++.h>
using namespace std;
typedef __int128 i128;
typedef long long ll;
typedef double db;
const db PI = acos(-1);
typedef array<ll, 2> PII; // vector<PII> a(n + 1);
const ll inf = 2e18 + 10;
const int mod = 998244353;
const int maxn = 1e5 + 10;
bool multi = 1;
void Solve() {
ll n; cin >> n;
vector<ll> a(maxn + 10);
for(ll i = 1; i <= n; i ++ ) {
ll x; cin >> x;
a[x] = 1;
}
ll cnt = 0;
for(ll i = maxn; i >= 1; i -- ) {
ll x = 0;
if(a[i] == 1) continue;
for(ll j = 1; j * i <= maxn; j ++ ) {
if(a[j * i]) {
if(x == 0) x = j * i;
else x = __gcd(x, j * i);
}
}
if(x == i) {
cnt ++ ;
a[i] = 1;
}
}
if(cnt % 2 == 1) cout << "dXqwq\n";
else cout << "Haitang\n";
}
signed main() {
// freopen("test.in","r",stdin);
// freopen("code.out","w",stdout);
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
ll T = 1;
if(multi) cin >> T;
while(T -- ) {
Solve();
}
return 0;
}
E.Haitang and Math
题意:
定义S(m)的值是m每一位上数字的和。
给定一个数字n,问有多少m<=n满足n%m=S(m).
1
<
=
n
<
=
1
0
12
1<=n<=10^{12}
1<=n<=1012
题解:
n
%
m
=
S
(
m
)
n\% m=S(m)
n%m=S(m) 等价于
n
−
S
(
m
)
=
k
×
m
n-S(m)=k \times m
n−S(m)=k×m
S(m)的范围就是0~108,可以找
n
−
S
(
m
)
n-S(m)
n−S(m)的因数,判断
m
<
=
n
m<=n
m<=n.
现在问题就是找到
[
n
−
108
,
n
]
[n-108,n]
[n−108,n]每个数的因数,枚举因数m判断是否满足条件。
但是n的范围很大,不能用用根号n的时间复杂度。我们使用区间筛法,
代码:
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e6+6;
const int M=108;
bool a[N] = { 1,1 };
int b[N],ans;
int v[500];
vector<pair<int,int>> e[500];
pair<int,int>su;
int sum(int x)
{
int re=0;
while(x){
re+=x%10;
x/=10;
}
return re;
}
void prime()
{
int cnt = 0;
for (int i = 2; i <= N; i++)
{
if (a[i] == 0) b[++cnt] = i;
for (int j = 1; j <= cnt; j++)
{
if (i * b[j] > N)break;
a[i * b[j]] = 1;
if (i % b[j] == 0)break;
}
}
}
#define pt vector<pair<int,int>>::iterator
void dfs(int x,pt s,pt t,int req)
{
if(s==t)
{//特判x!=req,因为要满足n%m<S(m)
if(sum(x)==req) ans+=(x!=req);
return ;
}
su=*s;
int y=su.first,z=su.second;
++s,dfs(x,s,t,req);
for(int i=1; i<=z; ++i)
x*=y,dfs(x,s,t,req);
return ;
}
void solve()
{
int n,k;
cin>>n;
if(n<=M){
ans=0;
for(int i=1;i<=n;i++){
if(n%i==sum(i))ans++;
}
cout<<ans<<'\n';
return ;
}
for(int i=0;i<=M;i++){
v[i]=n-i;
e[i].clear();
}
int cnt;
for(int i=1;1ll*b[i]*b[i]<=n;i++){
if(b[i]<=M){
for(int j=0;j<=M;j++){
cnt=0;
while(v[j]%b[i]==0){
cnt++;
v[j]/=b[i];
}
if(cnt){
e[j].push_back({b[i],cnt});
}
}
}else if(n%b[i]<=M){
int j=n%b[i];
cnt=0;
while(v[j]%b[i]==0){
cnt++;
v[j]/=b[i];
}
if(cnt){
e[j].push_back({b[i],cnt});
}
}
}
for(int i=0;i<=M;i++){
if(v[i]>1){
e[i].push_back({v[i],1});
}
}
ans=0;
for(int i=0;i<=M;i++){
dfs(1,e[i].begin(),e[i].end(),i);
}
cout<<ans<<'\n';
}
signed main()
{
// ios::sync_with_stdio(false);
// cin.tie(nullptr);
// cout.tie(nullptr);
prime();
int T = 1;
cin >> T;
while (T--) {
solve();
}
}
J.Haitang and Triangle
题意:
给定序列长度
n
n
n,构造长度为
n
n
n的的序列满足条件:
有
m
m
m个长度为3的子序列的数字可以构成一个三角形。
题解:
长度为
n
n
n的序列有n-2个长度为3的子序列。
1 1 1和任意另外两个数都不能构成三角形,所以 m = n − 2 m=n-2 m=n−2时不存在这样的序列。
序列是 [ 1 , 2 , 3 … … n ] [1,2,3……n] [1,2,3……n]时有m-3个子序列满足条件。
d
=
(
n
/
3
)
d=(n/3)
d=(n/3)
序列是
[
d
,
2
d
,
3
d
,
d
−
1
,
2
d
−
1
,
3
d
−
1
…
…
,
1
,
1
+
d
,
1
+
2
d
]
[d,2d,3d,d-1,2d-1,3d-1……,1,1+d,1+2d]
[d,2d,3d,d−1,2d−1,3d−1……,1,1+d,1+2d]时有0个子序列满足条件。
m是其他值时,可以可以搭配这两种序列排法,前n-m个数不应该有三角形子序列,用方法二构造,后
m
m
m个数用方法一构造,就刚好有
m
m
m个子序列可以构造出三角形。
现在考虑
(
n
−
m
)
m
o
d
3
(n-m) \mod 3
(n−m)mod3 有余数情况:
(
n
−
m
)
m
o
d
3
=
1
(n-m) \mod 3=1
(n−m)mod3=1,在前面插入
n
n
n.
(
n
−
m
)
m
o
d
3
=
2
(n-m) \mod 3=2
(n−m)mod3=2,在前面插入
3
d
+
1
3d+1
3d+1.后面插入
3
d
+
2
3d+2
3d+2。
剩下的数顺序放就行。
代码:
#include <bits/stdc++.h>
#define int long long
#define rep(i,j,k) for(int i=j;i<=k;i++)
using namespace std;
const int N=3e5+6;
int a[N],n,m;
void solve()
{
cin>>n>>m;
if(n==m+2){
cout<<"-1\n";
return ;
}
int d=(n-m)/3;
int t=1,x=3*d;
if((n-m)%3==1){
a[t++]=n;
x=3*d;
}
if((n-m)%3==2){
a[t++]=3*d+1;
}
int s1=d,s2=2*d,s3=3*d;
for(int i=d;i>=1;i--){
a[t++]=s1--;
a[t++]=s2--;
a[t++]=s3--;
}
if((n-m)%3==2){
a[t++]=3*d+2;
x=3*d+2;
}
x++;
for(int i=t;i<=n+1;i++){
a[i]=x++;
}
rep(i,1,n)cout<<a[i]<<' ';
cout<<'\n';
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
int T = 1;
cin >> T;
while (T--) {
solve();
}
}