牛客挑戰賽60
阿新 • • 發佈:2022-05-24
比較簡單的簽到題
點選檢視程式碼
#include<bits/stdc++.h> using namespace std; #define lowbit(x) x&(-x) #define ll long long int T; ll gcd(ll aa,ll bb){ if(bb)return gcd(bb,aa%bb); return aa; } int main(){ cin>>T; while(T--){ ll a,b; cin>>a>>b; ll gg=gcd(a,b); ll ag=a/gg,bg=b/gg; if(bg==1){ cout<<2*a<<endl; continue; } for(ll i=2;;i++){ if(gcd(i*ag,bg)==1){ cout<<i*a<<endl; break; } } } return 0; }
心路歷程:k的範圍1e5 n方是一定不行的 但是正解就是列舉就好
分析:因為只是中點 所以座標裡面最多隻有2×1000 × 2×1000的點 並且題目要求只是出現兩次就可以結束
那麼最壞的情況這些點全部都出現一次 下一個點一定會出現兩次
所以直接暴力列舉就好 這個題的想法不得不說很牛
點選檢視程式碼
#include <bits/stdc++.h> using namespace std; typedef pair<int,int> pii; const int N = 1e6 + 10; pii a[N]; int main() { int t; scanf("%d",&t); while (t --) { int n,m,k; scanf("%d%d%d",&n,&m,&k); map<pii,int> mp; int pos1 = -1,pos2 = -1; for(int i = 1;i <= k;i ++) scanf("%d%d",&a[i].first,&a[i].second); for(int i = 1;i <= k;i ++) for(int j = i + 1;j <= k;j ++) { mp[{a[i].first + a[j].first,a[i].second + a[j].second}] ++; if (mp[{a[i].first + a[j].first,a[i].second + a[j].second}] >= 2) { pos1 = i; pos2 = j; goto cc; } } cc: if (~pos1) { double x = (a[pos1].first + a[pos2].first) * 1.0 / 2.0; double y = (a[pos1].second + a[pos2].second) * 1.0 / 2.0; printf("YES %.1lf %.1lf\n",x,y); } else puts("NO"); } return 0; }
點選檢視程式碼
#include<bits/stdc++.h> using namespace std; #define lowbit(x) x&(-x) #define ll long long const int mod=1e9+7; int n; int main(){ cin>>n; ll ans=1; for(int i=1;i<=n;i++){ ll x;scanf("%lld",&x); ans=ans*(i-x+1)%mod; } cout<<ans<<endl; return 0; }
首先想到可以縮點 最後剩下一張拓撲圖 如果連通區域有多個 那麼一定無解
對於一個拓撲序唯一的 一定存在一個解 對於拓撲序不唯一的 也就是每次隊內元素>=2 一定是無解的
還有一個特別容易忽略的情況 那就是縮點後的強連通分量的大小為2 也就是有一個點對<a,b> 存在兩條邊a->b 和b->a
這樣任然無法滿足
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<string>
#include<algorithm>
#include<map>
#include<queue>
#include<stack>
#include<set>
#include<math.h>
#include<vector>
#pragma comment(linker,"/STACK:1024000000,1024000000")
#define pi acos(-1.0)
using namespace std;
typedef long long ll;
const double eps=1e-6;
const int maxn=100000+10;
const int maxm=200000+10;
const int INF=1361474528;
struct{
int to,w,next;
}edge[maxm];
int head[maxn],tot;
void Init(){
tot=0;
memset(head,-1,sizeof(head));
}
void addedge(int a,int b,int w){
edge[tot].to=b;
edge[tot].w=w;
edge[tot].next=head[a];
head[a]=tot++;
}
int dfn[maxn],low[maxn],scc[maxn],vis[maxn],stk[maxn],top,sccnum,indexx;
void tarjan(int x)
{
if(dfn[x])return ;
dfn[x]=++indexx;
vis[x]=1;
low[x]=dfn[x];
stk[top++]=x;
for(int i=head[x];i!=-1;i=edge[i].next)
{
int to=edge[i].to;
if(!dfn[to]){
tarjan(to);
low[x]=min(low[x],low[to]);
}
else if(vis[to])low[x]=min(low[x],dfn[to]);
}
if(dfn[x]==low[x])
{
sccnum++;
while(1)
{
int now=stk[--top];
scc[now]=sccnum;
vis[now]=0;
if(now==x)break;
}
}
}
void get_scc(int n)
{
memset(dfn,0,sizeof(dfn));
memset(low,0,sizeof(low));
indexx=0;top=0;sccnum=0;
for(int i=1;i<=n;i++)if(!dfn[i])tarjan(i);
}
int du[maxn];
vector<int>v[maxn];
queue<int>q;
int num[maxn];
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
Init();
for(int i=0;i<maxn;i++)v[i].clear(),du[i]=0,num[i]=0;
while(!q.empty())q.pop();
int n,m;
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
{
int a,b;
scanf("%d%d",&a,&b);
addedge(a,b,1);
}
get_scc(n);
for(int i=1;i<=n;i++)
{
num[scc[i]]++;
for(int j=head[i];j!=-1;j=edge[j].next)
{
int to=edge[j].to;
if(scc[i]==scc[to])continue;
du[scc[to]]++;
v[scc[i]].push_back(scc[to]);
}
}
int ok=1;
for(int i=1;i<=sccnum;i++)if(num[i]==2)ok=0;
for(int i=1;i<=sccnum;i++)
{
if(du[i]==0)q.push(i);
}
while(!q.empty())
{
int p=q.front();
q.pop();
if(!q.empty()){ok=0;break;}
for(int to:v[p])
{
du[to]--;
if(du[to]==0)q.push(to);
}
}
if(ok)printf("YES\n");
else printf("NO\n");
}
return 0;
}