Codeforces Round #686 (Div. 3) 题解

题目链接:Codeforces Round #686 (Div. 3)
A. Special Permutation

整体向后循环移一位

int main()
{
	int t;
	cin >> t;
	while(t--)
	{
		int n;
		cin >> n;
		for(int i=1;i<=n;i++)
		{
			if((i+1)%(n+1)==0) cout << 1 << ' ';
			else
				cout << (i+1)%(n+1) << ' ';
		}
		cout << endl;
	}
}

B. Unique Bid Auction

按题意模拟即可

int a[maxn],book[maxn];
int main()
{
	int t;
	cin >> t;
	while(t--)
	{
		memset(book,0,sizeof(book));
		int n;
		scanf("%d",&n);
		for(int i=1;i<=n;i++) 
		{
			scanf("%d",&a[i]);
			book[a[i]]++;
		}
		int pos=-1,minn=inf;
		for(int i=1;i<=n;i++)
		{
			if(book[a[i]]==1 && a[i]<minn)
			{
				minn=a[i];
				pos=i;
			}
		}
		printf("%d\n",pos);
	}
}

C. Sequence Transformation
#include<cmath>
#include<iostream>
#include<sstream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cstdlib>
#include<istream>
#include<vector>
#include<stack>
#include<set>
//#include<unordered_map>
#include<map>
#include<algorithm>
#include<queue>
#define mmp make_pair
#define inf 0x3f3f3f3f
#define llinf 0x7fffffffffffffff
using namespace std;
typedef long long ll;
typedef pair<int,int> PP;
typedef double ld;
struct A {
    int num,bz;
}a[200010];
bool cmp(A t1,A t2) {
    if(t1.num==t2.num)
         return t1.bz<t2.bz;
    else return t1.num<t2.num;
}
int main() {
    int T;
    scanf("%d",&T);
    while(T--) {
        int n;
        scanf("%d",&n);
        for(int i=1;i<=n;++i) {
            scanf("%d",&a[i].num);
            a[i].bz=i;
        }
        sort(a+1,a+1+n,cmp);
        /*for(int i=1;i<=n;++i) {
            cout<<a[i].bz<<" "<<a[i].num<<endl;
        }
        continue;*/
        int ans=inf;
        for(int i=1;i<=n;++i) {
            int h=i,t=i+1;
            while(a[t].num==a[h].num) ++t;
            --t;
            int temp=0;
            int sum=0;
            for(int j=h;j<=t;++j) {
                if(a[j].bz-temp>1) {
                    sum++;
                }
                temp=a[j].bz;
            }
           /* if(sum==0) {
                cout<<h<<" "<<t<<endl;
                for(int j=h;j<=t;++j) {
                    cout<<a[j].bz<<" "<<a[j].num<<endl;
                }
            }*/
            if(n-a[t].bz>=1) ++sum;
            ans=min(ans,sum);
            i=t;
        }
        printf("%d\n",ans);
    }
    return 0;
}

D. Number into Sequence

唯一分解,找到幂次最大的数字,答案就是幂次数-1个该数,以及n/pow(该数,幂次数-1)。

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<bitset>
#include<cassert>
#include<cctype>
#include<cmath>
#include<cstdlib>
#include<ctime>
#include<deque>
#include<iomanip>
#include<list>
#include<map>
#include<queue>
#include<set>
#include<stack>
#include<vector>
#include<unordered_set>
#include<unordered_map>
using namespace std;
//extern "C"{void *__dso_handle=0;}
typedef long long ll;
typedef long double ld;
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define pii pair<int,int>
#define lowbit(x) x&-x

const double PI=acos(-1.0);
const double eps=1e-6;
const ll mod=1e9+7;
const int inf=0x3f3f3f3f;
const int maxn=2e5+10;
const int maxm=100+10;
#define ios ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);

ll qpow(ll a,ll b)
{
	ll ans=1;
	while(b)
	{
		if(b&1) ans*=a;
		a*=a;
		b>>=1;
	}
	return ans;
}
int main()
{
	int t;
	cin >> t;
	while(t--)
	{
		ll n;
		scanf("%lld",&n);
		ll tmp=n,nt=sqrt(n);
		ll maxx=-1,num=0;
		for(int i=2;i<=nt;i++)
		{
			if(i>tmp) break;
			if(tmp%i==0)
			{
				ll sum=0;
				while(tmp%i==0)
				{
					sum++;
					tmp/=i;
				}
				if(maxx<sum)
				{
					maxx=sum;
					num=i;
				}
			}
		}
		if(tmp>1)
		{
			if(maxx<1)
			{
				maxx=1; num=tmp;
			}
		}
		printf("%lld\n",maxx);
		for(int i=1;i<maxx;i++) printf("%lld ",num);
		printf("%lld\n",n/qpow(num,maxx-1));
	}
}

E. Number of Simple Paths

由于n点n边,所以必有一环。那么整个图可以分为两种:环和非环(树)。

分情况讨论,环的简单路径个数为N*(N-1),非环(树)的简单路径个数为(N)*(N-1)/2,现在还有环与非环之间的简单路径以及非环与非环之间的简单路径。
环与非环之间的简单路径:xi*(N-1)*2(非环的点数)
非环与非环之间的简单路径: ∑ 1 c n t ∑ j = i + 1 c n t ( x [ i ] − 1 ) ∗ ( x [ j ] − 1 ) {\sum^{cnt}_{1}\sum^{cnt}_{j=i+1}(x[i]-1)*(x[j]-1)} 1cntj=i+1cnt(x[i]1)(x[j]1)
cnt为非环的连通分支数。

关于非环点数:由环上的每个点向外扩展不包括环其它点的个数(包含环上的扩展点)。
所以样例3中非环点数为:1 2 2

所以本题需先dfs记录环的每个点。但是可能会出现一个包含1e5个点的环以及环的每个点连接一个点。总共2e5个点的图。这样在计算非环与非环之间的简单路径时可能会达到 O ( ( 1 e 5 ) 2 ) {O((1e5)^2)} O((1e5)2)的时间复杂度。
所以需要优化, ( x [ i ] − 1 ) ∗ ( x [ j ] − 1 ) = x [ i ] ∗ x [ j ] − ( x [ i ] + x [ j ] ) + 1 {(x[i]-1)*(x[j]-1)=x[i]*x[j]-(x[i]+x[j])+1} (x[i]1)(x[j]1)=x[i]x[j](x[i]+x[j])+1
运用前缀和我们可以优化使之到达O(n)的时间复杂度来达到题目要求。

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<bitset>
#include<cassert>
#include<cctype>
#include<cmath>
#include<cstdlib>
#include<ctime>
#include<deque>
#include<iomanip>
#include<list>
#include<map>
#include<queue>
#include<set>
#include<stack>
#include<vector>

using namespace std;
//extern "C"{void *__dso_handle=0;}
typedef long long ll;
typedef long double ld;
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define pii pair<int,int>
#define lowbit(x) x&-x

const double PI=acos(-1.0);
const double eps=1e-6;
const ll mod=1e9+7;
const int inf=0x3f3f3f3f;
const int maxn=2e5+10;
const int maxm=100+10;
#define ios ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);

vector<int> g[maxn];
ll x[maxn],d[maxn];
vector<int> cir;
map<int,int> book;

int dfn[maxn],low[maxn];
int indx=0;
void dfs(int u,int f)
{
	dfn[u]=low[u]=++indx; 
	for(int i=0;i<g[u].size();i++)
	{
		int v=g[u][i];
		if(v==f) continue;
		if(dfn[v]==-1)
		{
			dfs(v,u);
			if(low[v]<low[u])
				{
					low[u]=low[v];
					cir.push_back(u);
				}
		}
		else if(dfn[v]<low[u])
		{
			cir.push_back(u);
			cir.push_back(v);
			low[u]=min(dfn[v],low[u]);
		}
	}
} 

int dfs1(int u,int f)
{
	int ans=1;
	for(int i=0;i<g[u].size();i++)
	{
		int v=g[u][i];
		if(v==f || book[v]) continue;
		ans+=dfs1(v,u);
	}
	return ans;
}
int main()
{
	int t;
	scanf("%d",&t);
	while(t--)
	{
		//memset(x,0,sizeof(x));
		book.clear();
		cir.clear();
		ll n;
		scanf("%lld",&n);
		for(int i=0;i<=n;i++) dfn[i]=-1;
		for(int i=1;i<=n;i++) g[i].clear();
		for(int i=1;i<=n;i++)
		{
			int u,v; scanf("%d%d",&u,&v);
			g[u].push_back(v);
			g[v].push_back(u);
		}
		dfs(1,0);
		ll T=cir.size();
		for(int i=0;i<T;i++) book[cir[i]]=1;
		int cnt=1;
		for(int i=0;i<T;i++)
		{
			x[cnt++]=dfs1(cir[i],0);
		}
		ll ans=T*(T-1);
		for(int i=1;i<cnt;i++)
		{
			ans+=x[i]*(x[i]-1)/2;
			ans+=(x[i]-1)*2*(T-1);
		}
		vector<ll> p;
		for(int i=1;i<cnt;i++)
		{
			if(x[i]>1) p.push_back(x[i]);
		}
		int len=p.size();
		if(len>0) d[0]=p[0];
		for(int i=1;i<len;i++) d[i]=d[i-1]+p[i];
		for(int i=0;i<len-1;i++)
		{
			ans+=2*(len-1-i)+2*(-((len-i-1)*p[i]+d[len-1]-d[i])+p[i]*(d[len-1]-d[i]));
		}
		printf("%lld\n",ans);
	}
}

 
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值