A. Coin Transformation
思路:思考一下,会发现能不超过每消耗一个4会产生一个2,因此我们有不超过4^x次方的硬币,最多只会变为2^(x-1)的硬币
直接敲代码即可
#include<bits/stdc++.h>
using namespace std;
#define int long long
int t;
int n,m,k;
int a[200005];
string s;
//快速幂公式
int fast(int a, int b)
{
long long result = 1;
long long base = a;
while (b > 0)
{
if (b % 2 == 1)
{
result = (result*base);
}
base = (base*base);
b /= 2;
}
return result;
}
void solve()
{
cin>>n;
int flag=1;
int ans=1;
if(n==1)
{
cout<<1<<"\n";
return ;
}
for(int i=1;i<=32;i++)
{
ans*=4;
flag+=1;
if(ans>n)
break;
}
flag--;
cout<<fast(2,flag)/2<<"\n";
}
signed main()
{
cin>>t;
while(t--)
{
solve();
}
return 0;
}
B. Digits
思路:通过分析后,会发现,数的各位数总和为为n!*d,我们可以发现,其实那个阶乘最大取到9就可以了,所以我们算出来n!*d,然后能够取模3等于0就说明3是可以的,取模9等于0就说明9也是可以的,只有d为5的时候才能包含5
我们来证明一下7的思路
我们首先可以将d全部都是1来处理,1%7=1,10%7=3,100%7=2,1000%7=6,10000%7=4,100000%7=5;
我们将前六项相加为21刚好可以整除7,所以只要n!>=6或者说n!*d整除7都是可以包含7的
1是必定被包含的
#include <bits/stdc++.h>
using namespace std;
#define int long long
int t;
int n, d;
int vis[10];
void solve()
{
cin >> n >> d;
int sum=1;
for(int i=1;i<=min(n,9LL);i++)
{
sum*=i;
}
sum*=d;
cout<<1<<" ";
if(sum%3==0)
{
cout<<3<<" ";
}
if(d==5)
{
cout<<5<<" ";
}
if(n>2)
{
cout<<7<<" ";
}
else if((11*d)%7==0)
{
cout<<7<<" ";
}
if(sum%9==0)
{
cout<<9<<" ";
}
cout << "\n";
}
signed main()
{
cin >> t;
while (t--)
{
solve();
}
return 0;
}
C. Sums on Segments
思路:我们首先来判断有没有不是-1或者1的值
假如没有,那么我么直接跑个线性dpO(n)求出最大最小值,里面的元素肯定在这个范围里面
假如有,那么我们将其分为两部分,一个是特殊值左边的区间,一个是特殊值右边的区间,都是去求最大最小值,然后将其与特殊值进行加法计算,算一个新的区间的值计入那个空间中,最后输出
#include<bits/stdc++.h>
using namespace std;
#define int long long
int t;
int n, m, k;
int a[200005];
set<int> s;
void solve()
{
s.clear();
cin >> n;
int num=0;
for (int i = 1; i <= n; i++)
{
cin >> a[i];
if(a[i]!=1&&a[i]!=-1)
num=i;
}
int maxn=0;//统计前缀最大值
int minn=0; //统计前缀最小值
int cntmin=0;
int cntmax=0;
if(num!=0)
{
for (int i = 1; i <= num-1; i++)
{
cntmin+=a[i];
cntmax+=a[i];
minn=min(minn,cntmin);
maxn=max(maxn,cntmax);
if(cntmin>0)
{
cntmin=0;
}
if(cntmax<0)
{
cntmax=0;
}
}
cntmin=0;
cntmax=0;
for (int i = num+1; i <= n; i++)
{
cntmin+=a[i];
cntmax+=a[i];
minn=min(minn,cntmin);
maxn=max(maxn,cntmax);
if(cntmin>0)
{
cntmin=0;
}
if(cntmax<0)
{
cntmax=0;
}
}
}
else
{
for (int i = 1; i <= n; i++)
{
cntmin+=a[i];
cntmax+=a[i];
minn=min(minn,cntmin);
maxn=max(maxn,cntmax);
if(cntmin>0)
{
cntmin=0;
}
if(cntmax<0)
{
cntmax=0;
}
}
}
for(int i=minn;i<=maxn;i++)
{
s.insert(i);
}
int premax=-0;
int premin=0;
int endmax=-0;
int endmin=0;
int ans=0;
if(num!=0)
{
for(int i=num-1;i>=1;i--)
{
ans+=a[i];
premax=max(premax,ans);
premin=min(premin,ans);
}
ans=0;
for(int i=num+1;i<=n;i++)
{
ans+=a[i];
endmax=max(endmax,ans);
endmin=min(endmin,ans);
}
for(int i=a[num]+premin+endmin;i<=a[num]+premax+endmax;i++)
{
s.insert(i);
}
}
cout<<s.size()<<"\n";
for(int u:s)
{
cout<<u<<" ";
}
cout<<"\n";
}
signed main() {
cin >> t;
while (t--) {
solve();
}
return 0;
}
D. Problem about GCD
我们可以将A视为a*G,B视为b*G,因此我们的gcd(a,b)=1,我们可以将左右区间缩小,同时整除G,但是我们的左区间要向上取整,右区间要向下取整,然后由于质数的稀疏性,我们完全可以只变脸左区间+20,以及右区间-20,然后找到互质的去处理即可
#include<bits/stdc++.h>
using namespace std;
#define int long long
int t;
int l, r, g;
string s;
int gcd(int a,int b)
{
if(b==0)
{
return a;
}
else
{
return gcd(b,a%b);
}
}
void solve()
{
cin >> l >> r >> g;
int L = (l+g-1)/g;
int R = r / g;
int maxn = -1;
int ansx = 1e15;
int ansy = -1;
for (int i = L; i <= min(R, L+20);i++)
{
for (int j = R; j >= max(i, R-20);j--)
{
if (gcd(i, j) == 1)
{
if (j - i > maxn)
{
ansx = i;
ansy = j;
maxn = j - i;
}
}
}
}
if (ansy == -1)
{
cout << -1<<" "<<-1<<"\n";
}
else
{
cout << ansx * g << ' ' << ansy * g << '\n';
}
}
signed main()
{
cin>>t;
while(t--)
{
solve();
}
return 0;
}
E. Matrix Transformation
思路:我们对题目上的操作进行化简,发现是以下的操作
操作1:将一整行变成0
操作2:将一整列变成1
因此我们可以用拆位的思想,将每个数都进行拆分成二进制位
然后逆向思维,先去看b数组,有0行就将0行删去,有1列就将1列删去,然后剩下的看两个数组是否相同即可,若相同就进行下一个比对,否则就是错的
#include <bits/stdc++.h>
using namespace std;
#define int long long
int T;
int n, m;
void solve()
{
cin >> n >> m;
vector<vector<int>> s(n, vector<int>(m));
vector<vector<int>> t(n, vector<int>(m));
for (int i = 0; i < n; ++i)
{
for (int j = 0; j < m; ++j)
{
cin >> s[i][j];
}
}
for (int i = 0; i < n; ++i)
{
for (int j = 0; j < m; ++j)
{
cin >> t[i][j];
}
}
bool ok = true;
for (int b = 0; b < 30 && ok; ++b)
{
vector<int> row(n), col(m), str(n), stc(m);
vector<vector<int>> v(n, vector<int>(m));
for (int i = 0; i < n; ++i)
{
for (int j = 0; j < m; ++j)
{
v[i][j] = (t[i][j] >> b) & 1;
if (!v[i][j])
{
col[j]++;
}
else
{
row[i]++;
}
}
}
vector<int> R, C;
for (int i = 0; i < n; ++i)
{
if (row[i] == 0)
{
R.push_back(i);
}
}
for (int j = 0; j < m; ++j)
{
if (col[j] == 0)
{
C.push_back(j);
}
}
while (true)
{
if (!R.empty())
{
int i = R.back();
R.pop_back();
str[i] = 1;
for (int j = 0; j < m; ++j)
{
if (stc[j] == 0 && v[i][j] == 0 && --col[j] == 0)
{
C.push_back(j);
}
}
}
else if (!C.empty())
{
int j = C.back();
C.pop_back();
stc[j] = 1;
for (int i = 0; i < n; ++i)
{
if (str[i] == 0 && v[i][j] == 1 && --row[i] == 0)
{
R.push_back(i);
}
}
}
else
{
break;
}
}
for (int i = 0; i < n; ++i)
{
for (int j = 0; j < m; ++j)
{
if (str[i] == 0 && stc[j] == 0 && v[i][j] != (s[i][j] >> b & 1))
{
ok = false;
break;
}
}
if (!ok) break;
}
}
cout << (ok ? "Yes" : "No") << '\n';
}
signed main()
{
cin >> T;
while (T--)
{
solve();
}
return 0;
}