20220303模擬賽題解and總結
阿新 • • 發佈:2022-03-03
總結
初一第一
一般,最後一題沒打好
不難發現,教練出水了,可能是信心賽
A.不幸的7
暴力,沒有邏輯可言
#include<bits/stdc++.h> using namespace std; int n,ans,t,k; bool pd(int x) { while(x) { if(x%10==7)return false; x/=10; } return true; } int main() { cin>>n; for(int i=1;i<=n;i++) { k=i,t=0; while(k) { t*=10; t+=k%8; k/=8; } if(pd(i)&&pd(t))ans++; } cout<<ans; }
一些沒用的感想
不難發現可以優化,完全不需要存下八進位制本題考察進位制轉換,不AC就該反思
B.選舉
簡單的貪心,思路很水,五分鐘想出來
先固定A,問題變成讓B追上A
A和B的初始的距離是什麼?
\[sumA=\sum_{i=1}^{n}a_i \]如果B什麼都不做,A可以獲得所有A支持者的選票
那一個城市能縮小多少距離呢
\[w_i=b_i+2a_i \]首先,去一個城市,B的支持者和A的支持者都支援B,就是\(b_i+a_i\),
A少了\(a_i\)個支持者,也加上去,就這樣
#include<bits/stdc++.h> using namespace std; struct node { long long a,b; }a[1000005]; long long n,suma,k; bool cmp(node x,node y) { return x.a*2+x.b>y.a*2+y.b; } int main() { cin>>n; for(int i=1;i<=n;i++) { scanf("%lld%lld",&a[i].a,&a[i].b); suma+=a[i].a; } sort(a+1,a+n+1,cmp); while(suma>=0) { k++; suma-=a[k].a*2+a[k].b; } cout<<k; }
關於真實的題目
其實沒什麼
真的
開long long
!,scanf
!
C. 差的絕對值之和
這道題水炸了,好好想,很有意思,不要直接看題解!
題解
先排序,按絕對值的性質,從大邊累加邊算,看看程式碼吧
#include <bits/stdc++.h> using namespace std; long long n, a[1000005], sum, ans; int main() { cin >> n; for (int i = 1; i <= n; i++) { cin >> a[i]; } sort(a + 1, a + n + 1); sum = a[n]; for (int i = n - 1; i >= 1; i--) { ans += sum - a[i] * (n - i); sum += a[i]; } cout << ans; }
有一個易錯點,ans += sum - a[i] * (n - i);
不要打成ans += sum - a[i] ;
,
這個數要和前面所有數計算
D. 路徑通過
整體操作,先明確父子關係,然後對於每個操作,理解為對整個樹和子樹的操作,
最後的dfs統計即可
#include<bits/stdc++.h>
using namespace std;
struct node
{
int t,next;
}a[500005];
long long n,m,x,y,z,tot,h[500005],fa[500005],s[500005],t[500005],w[500005],ans[500005];
void add(int x,int y)
{
tot++;
a[tot].t=y;
a[tot].next=h[x];
h[x]=tot;
}
void dfa(int x,int f)
{
for(int i=h[x];i;i=a[i].next)
{
if(a[i].t!=f)
{
fa[a[i].t]=x;
dfa(a[i].t,x);
}
}
}
void dfs(int x,int f)
{
ans[x]=ans[f]+w[x];
for(int i=h[x];i;i=a[i].next)
{
if(a[i].t!=f)
{
dfs(a[i].t,x);
}
}
}
int main()
{
cin>>n;
for(int i=1;i<=n-1;i++)
{
cin>>x>>y;
add(x,y);
add(y,x);
s[i]=x;
t[i]=y;
}
dfa(1,0);
cin>>m;
for(int i=1;i<=m;i++)
{
cin>>x>>y>>z;
if(x==1)
{
if(fa[t[y]]==s[y])
{
w[1]+=z;
w[t[y]]-=z;
}
else
{
w[s[y]]+=z;
}
}
else
{
if(fa[t[y]]==s[y])
{
w[t[y]]+=z;
}
else
{
w[1]+=z;
w[s[y]]-=z;
}
}
}
dfs(1,0);
for(int i=1;i<=n;i++)
{
cout<<ans[i]<<endl;
}
}
另一種做法
按dfs序,變成一個數組,然後樹狀陣列整體操作
這就是個Exgcd,我打出來真是萬幸,就是找正整數解那段忘了,自己的又臭又長
\[ s+1+xk \equiv 1(mod\ n) \]x為題目所求
化簡得
求即可
#include<bits/stdc++.h>
using namespace std;
long long t,a,b,c,x,y,gcd;
void exgcd(long long a,long long b,long long &x,long long &y)
{
if(!b)
{
// cout<<a<<' '<<b<<endl;
gcd=a;
x=1;
y=0;
return;
}
exgcd(b,a%b,y,x);
//cout<<a<<' '<<b<<' '<<x<<' '<<y<<endl;
y-=((a/b)*x);
}
int main()
{
cin>>t;
for(int i=1;i<=t;i++)
{
cin>>b>>c>>a;
x=0,y=0;
exgcd(a,-b,x,y);
if((-c)%gcd!=0)
{
cout<<-1<<endl;
continue;
}
x*=-c/gcd;
y*=-c/gcd;
if((a*-b)/gcd>0)
{
y-=(a*-b)/gcd/b*(x/(a*-b)/gcd/a);
x%=(a*-b)/gcd/a;
while(x<0)
{
x+=(a*-b)/gcd/a;
y-=(a*-b)/gcd/b;
}
y+=(a*-b)/gcd/b*(x/(a*-b)/gcd/a);
x%=(a*-b)/gcd/a;
while(x-((a*-b)/gcd)/a>=0)
{
x-=(a*-b)/gcd/a;
y+=(a*-b)/gcd/b;
}
}
else
{
y+=(a*-b)/gcd/b*(x/(a*-b)/gcd/a);
x%=(a*-b)/gcd/a;
while(x<0)
{
x-=(a*-b)/gcd/a;
y+=(a*-b)/gcd/b;
}
y-=(a*-b)/gcd/b*(x/(a*-b)/gcd/a);
x%=(a*-b)/gcd/a;
while(x+((a*-b)/gcd)/a>=0)
{
x+=(a*-b)/gcd/a;
y-=(a*-b)/gcd/b;
}
}
cout<<x<<endl;
}
}
第六題待做