特附今日闲话。
100+95+0+20.
赛时其实是看了一下样例和数据范围的一档说均为质数,无端的想到 gcd 于是就秒掉了。
其实因为这个减数、统计不重复的过程就类似于辗转相除吧。然后就没了。没什么说的,存一下码好了。
#include<bits/stdc++.h>
using namespace std;
int T,n;
int gcd(int x,int y){
if(!y) return x;
return gcd(y,x%y);
}
void solve(){
scanf("%d",&n);
int k=0,mx=0,ans=0;
for(int i=1;i<=n;i++){
int x;
scanf("%d",&x);
if(!k) k=x;
else k=gcd(k,x);
mx=max(mx,x);
}
for(int i=k;i<=mx;i+=k) ans++;
printf("%d\n",ans);
}
int main(){
freopen("num.in","r",stdin);
freopen("num.out","w",stdout);
scanf("%d",&T);
while(T--) solve();
}
次短路统计的板子喔,大概就是分两维的 dij。在 9.26 的这一场比赛 里做过这道题所以切了。考场一直在担心 dij 能不能跑过去,后来才意识到本题常见做法只有 dij 了...
你问我为什挂了 5 分?因为没有判次短路是不是严格符合要求(比最短路小 1)。
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=2e6+10;
const ll mod=998244353;
int n,m;
ll cnt[N][2];
int vis[N][2],d[N][2];
int idx,e[N],nxt[N],head[N];
void add(int x,int y){
e[++idx]=y;
nxt[idx]=head[x];
head[x]=idx;
}
void dij(){
priority_queue<pair<pair<int,int>,int> > q;
memset(d,0x3f,sizeof d);
q.push(make_pair(make_pair(0,1),0));
d[1][0]=0;
cnt[1][0]=1;
while(q.size()){
int x=q.top().first.second,t=q.top().second;
q.pop();
if(vis[x][t]) continue;
vis[x][t]=1;
for(int i=head[x];i;i=nxt[i]){
if(d[e[i]][0]>d[x][t]+1){
d[e[i]][1]=d[e[i]][0],cnt[e[i]][1]=cnt[e[i]][0];
q.push(make_pair(make_pair(-d[e[i]][1],e[i]),1));
d[e[i]][0]=d[x][t]+1,cnt[e[i]][0]=cnt[x][t];
q.push(make_pair(make_pair(-d[e[i]][0],e[i]),0));
}
else if(d[e[i]][0]==d[x][t]+1) cnt[e[i]][0]=(cnt[e[i]][0]+cnt[x][t])%mod;
else if(d[e[i]][1]>d[x][t]+1){
d[e[i]][1]=d[x][t]+1,cnt[e[i]][1]=cnt[x][t];
q.push(make_pair(make_pair(-d[e[i]][1],e[i]),1));
}
else if(d[e[i]][1]==d[x][t]+1) cnt[e[i]][1]=(cnt[e[i]][1]+cnt[x][t])%mod;
}
}
}
int main(){
scanf("%d%d",&n,&m);
while(m--){
int x,y;
scanf("%d%d",&x,&y);
add(x,y);
add(y,x);
}
dij();
if(d[n][0]+1!=d[n][1]||!d[n][0]||d[n][0]==0x3f3f3f3f) puts("0");
else printf("%lld\n",cnt[n][1]);
}
正解还没补,大概是离线下来线段树 + 并查集。我觉得我赛前只需要尽力补一补暴力能力。
赛时,好像最后一个小时脑子都是糊涂的。想当然的写了个链的性质赛后就发现假了。20pts 的爆搜又不会写。
所以赶紧补了一下树上搜。现在会了。这是 20pts 的码。
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=3e5+110;
int n,q,k;
ll ans;
int vis[N];
int idx,e[N],w[N],nxt[N],head[N];
void add(int x,int y,int z){
e[++idx]=y;
w[idx]=z;
nxt[idx]=head[x];
head[x]=idx;
}
void dfs(int x){
vis[x]=1;
for(int i=head[x];i;i=nxt[i]){
if(w[i]>k) continue;
if(!vis[e[i]]){
ans+=w[i];
dfs(e[i]);
}
}
}
int main(){
scanf("%d",&n);
for(int i=2;i<=n;i++){
int x,z;
scanf("%d%d",&x,&z);
add(x,i,z);
}
scanf("%d",&q);
while(q--){
int u;
scanf("%d%d",&u,&k);
dfs(u);
printf("%lld\n",ans);
memset(vis,0,sizeof vis);
ans=0;
}
}
同上,感觉不需要补了,这是 30pts 的暴力。赛时为什么暴力还挂成 20pts 了呢,因为快速幂忘记开 long long 炸掉了。
#include<bits/stdc++.h>
#define ull unsigned long long
#define ll long long
using namespace std;
const int N=2e5+10;
const ll mod=998244353;
int n,a,b;
ll ans;
int t[N];
map<ull,int> vis;
bool check(int m){
if(m==1) return 1;
for(int i=1;i<=m;i++)
for(int j=i+1;j<=m;j++)
if(t[i]*a==t[j]||t[j]*a==t[i]||t[i]*b==t[j]||t[j]*b==t[i]) return 0;
return 1;
}
void js(int m){
ull tot=0;
for(int i=1;i<=m;i++) tot=tot*131+t[i]*131;
if(!vis[tot]){vis[tot]=1;ans++;}
}
void dfs(int x,int tot){
if(check(tot)) js(tot);
if(x==n+1) return;
t[tot+1]=x;
dfs(x+1,tot+1);
t[tot+1]=0;
dfs(x+1,tot);
}
ll ksm(ll a,ll b){
ll tot=1;
while(b){
if(b&1) tot=(tot*a)%mod;
b>>=1;
a=(a*a)%mod;
}
return tot%mod;
}
int main(){
scanf("%d%d%d",&n,&a,&b);
if(a==1&&b==1){
printf("%lld",ksm(2,n));
return 0;
}
if(n<=15){
dfs(1,0);
printf("%lld",ans);
return 0;
}
}
标签:cnt,idx,int,ll,head,long,11.10,模拟,小记
From: https://www.cnblogs.com/Moyyer-suiy/p/17824910.html