星期一:
军训结束,正式成为一名退伍老兵。若有战,召必回!
12月16号考六级,17号重庆市赛,这个月得狠狠上强度啊。
话接上回的B题:
题意:乍看差点以为是道树题,差点直接run了。还好先读完了题。一棵未知的树,有bfs经过的点的顺序,求可能树的最小高度。bfs对于同一父节点的所有点升序访问。
思路:这题的样例给的极其简单,导致我先交了发极其简单的代码,wa2。随即发现情况并不止样例这么简单,不过也就是道模拟。
代码如下:
#include <bits/stdc++.h>
using namespace std;
using ll=long long;
using PII=pair<int,int>;
const int N=2e5+10;
int n;
int a[N];
int ans,las,tmp;
void solve(){
ans=1;las=1;tmp=1;
cin >> n;
for(int i=1;i<=n;i++){
cin >> a[i];
}
for(int i=3;i<=n;i++){
if(a[i]>a[i-1]){
tmp++;
}else{
las--;
if(!las){
ans++;
las=tmp;
tmp=1;
continue;
}
tmp++;
}
}
cout << ans << endl;
}
int main(){
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
int t=1;
cin >> t;
while(t--) solve();
return 0;
}
//make it count
//开ll plz
星期二和李,强打了场广西市赛,效果还不错。
比赛B题:
题意:自行理解
思路:给2做个特判,其余为26 0 26的n次幂-26。所以需要用到快速幂,这里记录一个%的细节
代码如下:
#include <bits/stdc++.h>
using namespace std;
using ll=long long;
using PII=pair<int,int>;
const int N=2e5+10;
const ll mod=1e9+7;
int n;
int a[N];
ll ask(ll a,ll n,ll m){
if(n==0) return 1;
if(n==1) return a;
ll s=ask(a,n/2,m);
s=s*s%m;
if(n%2==1) s=s*a%m;
return s;
}
void solve(){
cin >> n;
if(n==2){cout << "26 650 0"; return ;}
ll ans=(ask(26,n,mod)-26+mod)%mod;
cout << "26 0 " << ans;
}
int main(){
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
int t=1;
// cin >> t;
while(t--) solve();
return 0;
}
//make it count
//开ll plz
这里有一个需要注意的地方,就是这句
ll ans=(ask(26,n,mod)-26+mod)%mod;
当时一开始写的是
ll ans=ask(26,n,mod)-26;
没有考虑到的是,ans在取模后可能是一个小于26的值,所以减26后可能小于0,所以需要再加一个mod再取模一次。比赛时因为没考虑到这点,感觉被耽误了可能得有1个小时。消耗的不止时间,还有精力,搞的后面没力气做题了。
再记录下学到了的一道题:
题意:判断能否仅通过复制粘贴将字符串s变为t(复制只能全选)
思路:按我的思路来的话,需要遍历一下t,遍历到不相同的字符会退出,遍历完后判断t是否为s的2次幂数倍。但在网上看到了个更牛的思路,直呼学到了。
代码如下:
#include <bits/stdc++.h>
using namespace std;
using ll=long long;
using PII=pair<int,int>;
const int N=1e5+10;
int n;
string s,t;
void solve(){
cin >> s >> t;
while(s.size()<t.size()) s+=s;
if(s==t) cout << "win";
else cout << "failure";
}
int main(){
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
int t=1;
//cin >> t;
while(t--) solve();
return 0;
}
//make it count
//开ll plz
直接模拟,非常美丽的思路和代码啊。
再补俩题:
H题:
题意:寻找满足条件的正整数有多少个,条件如下。给一a,x不大于a。给m个b和c,b%x=c。
思路:一开始想的是,对于每次b,c,找出b-c的因数集合,对所有集合取交集。但wa
代码如下:
#include <bits/stdc++.h>
using namespace std;
using ll=long long;
using PII=pair<int,int>;
const int N=1e5+10,M=1e8;
void solve(){
ll m,maxx,minn=0;
ll ans=0;
vector<pair<int,bool>>ve;
cin >> m >> maxx;
for(int i=1;i<=m;i++){
ll b,c;
cin >> b >> c;
minn=max(c,minn);
if(i==1){
for(int j=1;j*j<=(b-c);j++){
if((b-c)%j==0){
if(j<=maxx) ve.push_back({j,1});
if(j*j==b-c) break;
if((b-c)/j<=maxx) ve.push_back({(b-c)/j,1});
}
}
continue;
}
for(int j=0,k=ve.size();j<k;j++){
if(b==0) continue;
if((b-c)%ve[j].first) ve[j].second=0;
}
}
for(int i=0,j=ve.size();i<j;i++){
if(ve[i].second && ve[i].first>minn && ve[i].first<=maxx) ans++;
}
// for(int i=0,j=ve.size();i<j;i++){
// cout << ve[i].first << " " << ve[i].second << endl;
// }
cout << ans;
}
int main(){
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
int t=1;
//cin >> t;
while(t--) solve();
return 0;
}
//make it count
//开ll了没
然后看题解,发现可以取所有b-c的gcd,效果是一样的,且方便实现。(也不是很方便
代码如下:
#include <bits/stdc++.h>
using namespace std;
using ll=long long;
using PII=pair<int,int>;
const int N=1e5+10,M=1e8;
int m;
ll a,minn=1;
ll gc,ans;
int gcd(int a,int b){
return b==0?a:gcd(b,a%b);
}
void solve(){
cin >> m >> a;
while(m--){
ll b,c;
cin >> b >> c;
gc=gcd(b-c,gc);
minn=max(c,minn);
}
if(!gc){cout << a-minn; return ;}
// for(int i=1;i<=gc/i;i++){
// if(gc%i==0 && gc/i>minn && gc/i<=a) ans++;
// }
for(int i=1;i<=gc/i;i++){
if(gc%i==0){
if(i<=a && i>minn) ans++;
if(gc/i!=i && gc/i<=a && gc/i>minn) ans++;
}
}
cout << ans;
}
int main(){
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
int t=1;
//cin >> t;
while(t--) solve();
return 0;
}
//make it count
//开ll了没
D题:
题意:3n个人组成n个队伍,给出m对熟悉关系,间接熟悉也算熟悉,每人的焦虑值为同队中不熟悉的人的数量,问焦虑值总和的最小。
思路:并查集,但很久没写并查集了,刚好练练。
代码如下:
#include <bits/stdc++.h>
using namespace std;
using ll=long long;
using PII=pair<int,int>;
const int N=3e6+10;
int n,m;
int fa[N],num[N];
int a,b,ans;
int fnd(int x){
return x==fa[x]?x:fa[x]=fnd(fa[x]);
}
void solve(){
cin >> n >> m;n*=3;
for(int i=1;i<=n;i++) fa[i]=i,num[i]=1;
while(m--){
int x,y;
cin >> x >> y;
x=fnd(x),y=fnd(y);
if(x!=y){
fa[x]=y;
num[y]+=num[x];
}
}
for(int i=1;i<=n;i++){
if(fa[i]==i){
if(num[i]%3==1) b++;
if(num[i]%3==2) a++;
}
}
// cout << a << " " << b << endl;
if(a>=b) ans=b*4+(a-b)/3*8;
else ans=(a+b)*2;
cout << ans;
}
int main(){
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
int t=1;
//cin >> t;
while(t--) solve();
return 0;
}
//make it count
//开ll plz
不过目前我还没搞懂 ans=(a+b)*2 怎么来的。
再补几道比赛没来得及看,但也许可以做做的题。
看了下,好像补不是很了。
星期四:
20号(星期一的每日三题:
A题:
题意:自行理解
思路:数据不大,思路难想。我最开始的思路是对于每个ti,向两边扩散寻找取出时间,但wa2,思路错了
记录下代码:
#include <bits/stdc++.h>
using namespace std;
using ll=long long;
using PII=pair<int,int>;
const int N=2e5+10,M=1e9+10;
const int mod=998244353;
int n;
int a[210];
bool vi[1000];
int ans;
void solve(){
memset(vi,0,sizeof(vi));
ans=0;
cin >> n;
for(int i=1;i<=n;i++){
cin >> a[i];
}
sort(a+1,a+n+1);
for(int i=1;i<=n;i++){
int j=a[i],k=a[i];
while(vi[j] && vi[k]){
j--,k++;
if(j==0) j++;
}
if(!vi[j]) vi[j]=1,ans+=a[i]-j,cout << j << endl;
else vi[k]=1,ans+=k-a[i],cout << k << endl;
// for(int y=1;y<=6;y++) cout << vi[y] << " ";cout << endl;
}
cout << ans << endl;
}
int main(){
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
int t=1;
cin >> t;
while(t--) solve();
return 0;
}
//make it count
//开ll plz
去hack了下数据,发现是道1800的题,且有dp标签,尝试从dp角度切入。
。。。(我讨厌dp)
啃了半天题解,做不了一点,麻了。
记录下学到的memset函数初始化最大值
memset(a,0x3f,sizeof(a));
经过半天(字面意义上),终于勉强算是拿下了这道dp。
dp[i][j]表示考虑到前i个菜,在j时刻最小不新鲜值。dp数组的初始化需要注意。
代码如下:
#include <bits/stdc++.h>
using namespace std;
using ll=long long;
using PII=pair<int,int>;
const int N=2e5+10,M=1e9+10;
const int mod=998244353;
int n;
int a[210];
int dp[210][440];
int ans;
void solve(){
memset(dp,0x3f,sizeof(dp));
ans=INT_MAX;
cin >> n;
for(int j=0;j<=2*n;j++) dp[0][j]=0;
for(int i=1;i<=n;i++){
cin >> a[i];
}
sort(a+1,a+n+1);
for(int i=1;i<=n;i++){
for(int j=1;j<=n*2;j++){
dp[i][j]=min(dp[i][j-1],dp[i-1][j-1]+abs(a[i]-j));
}
}
// for(int j=1;j<=2*n;j++) ans=min(dp[n][j],ans);
cout << dp[n][n*2] << endl;
}
int main(){
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
int t=1;
cin >> t;
while(t--) solve();
return 0;
}
//make it count
//开ll plz
星期五:
题意:自行理解
思路:
(一天拿不下一道题,woyouzui)
晚上打了场div2,找时间补补c和d题
星期六打了场复活赛,比较有悬念地拿下了,但过的都是基础题,胜在罚时。
记录一个getline相关的操作,今一题遇到需要用到getline的情况,但cin.clear()好像没起作用,所以我把cin换成了scanf,还是不行。该怎么操作呢,如下(在cin之后使用):
s="\n";
getline(cin,s);
第二天回想起,cin和getline混用,不是用cin.clear(),是用cin.ignore() 啊,佛了
记录一道有价值的题,赛时没a,赛后补的,比较吃细节。
题意:自行理解
思路:我最开始想到的是贪心模拟,二分貌似也行,先不管。
代码如下:
#include <bits/stdc++.h>
using namespace std;
using ll=long long;
using PII=pair<int,int>;
const int N=2e5+10;
const int mod=998244353;
int n,m;
ll maxx,minn;
bool iff,iif;
void solve(){
int c,d;
cin >> n;
cin >> c >> d;
if(d==1) iif=1,minn=1900;
else iff=1,maxx=1899;
minn+=c,maxx+=c;
for(int i=2;i<=n;i++){
cin >> c >> d;
if(d==1){
if(iff && maxx<1900){cout << "Impossible"; return ;}
if(!iif) iif=1,minn=1900;
minn+=c,maxx+=c;
}else{
if(iif && minn>=1900){cout << "Impossible"; return ;}
if(!iff) iff=1,maxx=1899;
if(maxx>1899) maxx=1899;
minn+=c,maxx+=c;
}
}
if(!iff){cout << "Infinity"; return ;}
cout << maxx;
}
int main(){
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
int t=1;
//cin >> t;
while(t--) solve();
return 0;
}
//make it count
//开ll了没
还有E,F,I题都可以补。
星期天打了场沙东省赛,花了两小时,做了5道签到题就run了,罚时很不理想,主要有两道题犯病了,耽误了时间。记录一道签到题犯病过程:
题意:初始有n金币,每次死亡掉一半,向上取整需注意,问死k次后剩多少金币。
思路:开始时脑阔短路,觉得直接模拟会tle。。嗯是让我搞了个莫名其妙的式子出来,后来强模拟时用double和ceil函数,wa2了,就给改成了int和手动ceil,ac。真耽误了很多时间这里,本来应该秒的
晚上打了场div2,第一次过3题,舒服.