可分解的正整数
算法:思维
因为可以有负数 所以除了1以外的任何数都可以构造
当这个数为x构造方法为
-(x-1) -(x-2) -(x-3) ....-1 0 1...x-3 x-2 x-1 x
除了x,x以前的数都会被负数抵消
#include <bits/stdc++.h>
#define ll long long
ll a[100005];
using namespace std;
int main() {
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
ll n;cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i];
}
ll ans=0;
for(int i=1;i<=n;i++){
if(a[i]!=1) ans++;
}
cout<<ans<<"\n";
return 0;
}
产值调整
算法:思维 打表
当三个数相同时 不管怎么调整 结果不会发生改变,所以当三个数相同时break即可
根据模拟题目要求打表后发现,调整100次后 所有数都会变成相同的,所以break后不会使代码超时
#include <bits/stdc++.h>
#define ll long long
ll a[100005];
using namespace std;
int main() {
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
ll t;cin>>t;
while(t--){
ll a,b,c,k;cin>>a>>b>>c>>k;
for(int i=1;i<=k;i++){
ll na,nb,nc;
na=(b+c)/2;
nb=(a+c)/2;
nc=(a+b)/2;
a=na;b=nb;c=nc;
if(a==b and b==c) break;
}
cout<<a<<" "<<b<<" "<<c<<" "<<"\n";
}
return 0;
}
画展布置
算法:前缀和
观察计算公式 需要用到的数皆为平方 提前处理 将每个数平方后 公式将被简化为 每两个数之间的差的和 贪心的思考 使得一组数相邻两个数之间差的和最小 数组有序为最优 先排序 排序后枚举开始的位置 求当前位置到当前位置+m位置的差的和 使用前缀和预处理每个位置的前缀和查询即可。
#include <bits/stdc++.h>
#define ll long long
ll a[100005],b[100005],c[100005];
using namespace std;
int main() {
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
ll n,m;cin>>n>>m;
for(int i=1;i<=n;i++){
cin>>a[i];
}
sort(a+1,a+1+n);
for(int i=1;i<n;i++){
b[i]=a[i+1]*a[i+1]-a[i]*a[i];
}
for(int i=1;i<n;i++){
c[i]=c[i-1]+b[i];
}
ll ans=1e18;
for(int i=1;i<=n-m+1;i++){
ans=min(ans,c[i+m-2]-c[i-1]);
}
cout<<ans<<"\n";
return 0;
}
水质检测
算法:模拟
按题目要求模拟即可,唯一需要贪心的点,即为
#. .#
的情况 从左往右判断时 若要使它们联通 最优的方案为
## .#
#include <bits/stdc++.h>
#define ll long long
using namespace std;
int main() {
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
string s[2];cin>>s[0]>>s[1];
ll n=s[0].size();
s[0]=" "+s[0];s[1]=" "+s[1];
ll ans=0;
ll l=0,r=0;
for(int i=1;i<=n;i++){
if((s[0][i]=='#' || s[1][i]=='#') && l==0){
l=i;
}
if((s[0][i]=='#' || s[1][i]=='#')){
r=i;
}
}
ll cnt=-1;
if(s[0][l]=='.' && s[1][l]=='#') cnt=1;
if(s[1][l]=='.' && s[0][l]=='#') cnt=0;
for(int i=l+1;i<=r;i++){
if(s[0][i]=='.' && s[1][i]=='.'){
ans++;
}else if(s[0][i]=='#' && s[1][i]=='.'){
if(cnt==1){
cnt=-1;
ans++;
}else{
cnt=0;
}
}else if(s[0][i]=='.' && s[1][i]=='#'){
if(cnt==0){
cnt=-1;
ans++;
}else{
cnt=1;
}
}else{
cnt=-1;
}
}
cout<<ans<<"\n";
return 0;
}
生产车间
算法:树形DP/树上DP
先考虑这道题 但没考虑出来 开始蹭分
于是输出根的权值获得(洛谷50%)
#include <bits/stdc++.h>
#define ll long long
using namespace std;
ll a[1005];
int main() {
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
ll n;
cin>>n;
ll ans=0;
for(int i=1;i<=n;i++){
cin>>a[i];
}
for(int i=1;i<n;i++) {
ll o,p;cin>>o>>p;
}
cout<<a[1];
return 0;
}
装修报价
方案1:DFS爆搜(30%分)
算法:DFS
为每两个数字之间遍历它们是否为异或。如果当前位置为异或,则提前计算,并储存它们异或后的数字序列。 然后遍历每个位置是‘+’还是‘-’并计算,加入答案。
#include <bits/stdc++.h>
#define ll long long
ll a[100005];
using namespace std;
const ll MOD = 1e9 + 7;
ll ans=0;ll n;
void dfs2(vector<ll> v){
if(v.size()==1){
ans+=v[0];
ans%=MOD;
return;
}
ll it=v[v.size()-1];
v.pop_back();
v[0]+=it;
dfs2(v);
v[0]-=it;
v[0]-=it;
dfs2(v);
}
void dfs(vector<ll> v,ll x){
if(x>n) {
dfs2(v);
return;
}
v.push_back(a[x]);
dfs(v,x+1);
v.pop_back();
if(v.size()){
ll tp=v[v.size()-1];
v[v.size()-1]^=a[x];
dfs(v,x+1);
v[v.size()-1];
}
}
int main() {
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
cin>>n;
vector<ll> d;
ll now=0;
for(int i=1;i<=n;i++){
cin>>a[i];now^=a[i];
}
dfs(d,1);
cout<<ans<<"\n";
return 0;
}
方案2:数学 规律 打表(100%分)
时间复杂度:O(n)
每个数字后都存在‘+’和‘-’,无论之后的数字间填写什么符号,结果都会被抵消,但从第一个位置异或到第i个位置的答案会保留(1<=i<=n)。
位置1异或到3 (1组)
0⊕2⊕5=7
位置1异或到2 (2组)位置3和它之后的都被抵消
0⊕2 +5=7
0⊕2 −5=−3
位置1 (6组) 位置2和它之后的都被抵消
0 +2⊕5=7
0 −2⊕5=−7
0 +2−5=−3
0 −2+5=3
0 +2+5=7
0 −2−5=−7
所以最后的结果为
第一个数字 1组
第一个数字异或到第二个数字 2组
第二个数字异或到第三个数字 6组
第三个数字异或到第四个数字 18组
从第n-1个数字前 每个位置的组数是后一个的三倍 依次递增求和即可
#include <bits/stdc++.h>
#define ll long long
ll a[100005];
using namespace std;
const ll MOD = 1e9 + 7;
ll ans=0;ll n;
int main() {
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
cin>>n;
vector<ll> d;
ll now=0;
for(int i=1;i<=n;i++){
cin>>a[i];now^=a[i];
}
ll op=2;
ans+=now;
now^=a[n];
ll tp=0;
for(int i=n-1;i>=1;i--){
ans+=now*op;
ans%=MOD;
now^=a[i];
op*=3;
op%=MOD;
}
ans%=MOD;
ans+=MOD;
ans%=MOD;
cout<<ans<<"\n";
return 0;
}