Welcome back (题解:D

以下我的简单题解,网上题解很多...

A:https://codeforces.com/contest/1110/problem/A

以下性质:

1:偶*偶,奇*偶,为偶数,奇*奇为奇数。

2:x如果为奇数,x^n也是奇数,偶数同理。

就可以轻松切了这题。

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<climits>
using namespace std;


int main (){
	int b,k,a[100005];
	cin>>b>>k;
	for(int i=1;i<=k;i++)
	 scanf("%d",&a[i]);
	int re=0;
	for(int i=1;i<k;i++){
		int x=b%2,y=a[i]%2;
		if(x%2==0||y%2==0) re=re+0;
		else re=(re+1)%2; 
	}
	if(a[k]%2) re=(re+1)%2;
	if(re%2) cout<<"odd";
	else cout<<"even";
	return 0;
}

B:https://codeforces.com/problemset/problem/1076/C

由 a+b=da*b=d,可得:a{^{2}}-a*d+d=0

然后就是高中数学题

d*d<4*d时无解,否则一组解是\frac{d+sqrt(d*d-4*d))}{2}d-\frac{d+sqrt(d*d-4*d))}{2}

以下lhm代码(:D)

#include<iostream>
using namespace std;
int main(){
	double d;
	int t;
	scanf("%d", &t);
	while (t--)
	{
		scanf("%lf", &d);
		if (d*d < 4 * d)
			printf("N\n");
		else
		{
			double tt = d*d - 4.0 * d;
			double an = d + (double)sqrt(tt);
			an = an / (double)2;
			printf("Y %.9lf %.9lf\n", an, d - an);
		}
	}
	return 0;
}

此题也可根据函数单调性二分....

以下cb代码

#include<stdio.h>
#include<queue>
#include<cstring>
using namespace std;
const int maxn=100000+30;
#define dou double
dou bSearch(dou d)  
{  
    dou mid,left=0,right=d;  
    if(!d) return 0;
    while(left<=right)  
    {  
        mid=(left+right)/2;  
        if(d-mid>=d/mid) right=mid-0.0000000001;  
        else left=mid+0.0000000001;  
    }
    return left;  
}
int main()
{
	int n;
	scanf("%d",&n);
	while(n--)
	{	
		dou d;
		scanf("%lf",&d);	
		if(d<4&&d>0) puts("N");
		else if(d==4) printf("Y 2.000000000 2.000000000\n");
		else{
			dou temp=bSearch(d);	
			printf("");
			printf("Y %.9lf %.9lf\n",d-temp,temp);
		}
	}
	return 0;
}

C:http://acm.hdu.edu.cn/showproblem.php?pid=1042

大数模拟,注意细节。

/*   Author : Rshs
 *   Data : 2019-09-09-18.23
 */
#include<bits/stdc++.h>
using namespace std;
#define FI first
#define SE second
#define LL long long
#define MP make_pair
#define PII pair<int,int>
#define SZ(a) (int)a.size()
const double pai = acos(-1);
const LL mod = 1e9+7;
const int MX = 1e6+5;

struct no{
    int le; //长度
    int a[MX]; //大数
}n;

void mul(int x){  //求n*x,封装到n里
    reverse(n.a,n.a+n.le); //先反过来,好处理
    for(int i=0;i<n.le;i++) n.a[i]*=x;//先乘,
    for(int i=0;i<n.le;i++){ //再统一进位
        int yu=n.a[i]%10;
        int jin=n.a[i]/10;
        n.a[i+1]+=jin;
        n.a[i]=yu;
    }
    if(n.a[n.le]) n.le++; //le处有进数
    while(n.a[n.le-1]>=10){//不断处理le处的进数
        int yu=n.a[n.le-1]%10;
        int jin=n.a[n.le-1]/10;
        n.a[n.le]+=jin;
        n.a[n.le-1]=yu;
        n.le++;
    }
    reverse(n.a,n.a+n.le); //最后再反过来
}

int main(){

    int nn;
    int last=0;//记录上次长度,用于清空
    while(cin>>nn){
            //初始化
        for(int i=0;i<=last;i++)n.a[i]=0;
        n.le=1;n.a[0]=1;
        for(int i=1;i<=nn;i++)mul(i);
        for(int i=0;i<n.le;i++) cout<<n.a[i];
        puts("");
        last=n.le;
    }
    return 0;
}

zm精简代码 (:D)

#include<cstdio>
int a[10017];
int main(){
    int i,j,jin,n;
    while(~scanf("%d",&n)){
        for(int i=0;i<10000;++i)a[i]=0;
        jin=0;a[0]=1;
        for(i=1;i<=n;i++){
        	for(j=0;j<=jin;j++){
	            a[j]=a[j]*i;
	            if(j>0&&a[j-1]>10000){
	                a[j]=a[j]+a[j-1]/10000;
	                a[j-1]=a[j-1]%10000;
	            }
	            if(a[jin]>=10000) jin++;
	        }
        }
        printf("%d",a[jin]);
        for(i=jin-1;i>=0;i--) printf("%04d",a[i]); printf("\n");
    }           
}

D:http://poj.org/problem?id=3278

从农夫的起点bfs即可,或者记忆化dfs

以下wqq代码(:D)

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
using namespace std;
typedef long long ll;
typedef pair<ll,ll> P;
const int inf=0x3f3f3f3f;
const int maxn=1e5+10;
int n,b,k,ans=0;
bool vis[maxn];
int bfs(){
    queue<P> q;
    q.push(make_pair(n,0));
    while(!q.empty()){
        P now= q.front();q.pop();
        if(now.first==k){
            return now.second;
        }
        if(now.first+1<=100000&&!vis[now.first+1]){//向右
            vis[now.first+1]=1;q.push(make_pair(now.first+1,now.second+1));
        }
        if(now.first-1>=0&&!vis[now.first-1]){//向左
            vis[now.first-1]=1;q.push(make_pair(now.first-1,now.second+1));
        }
        if(now.first*2<=100000&&!vis[now.first*2]){ //向两倍的地方走
            vis[now.first*2]=1;q.push(make_pair(now.first*2,now.second+1));
        }
    }
    return 0;
}
int main()
{
    scanf("%d%d",&n,&k);
    if(n>=k)ans=n-k;
    else ans=bfs();
    printf("%d\n",ans);
    return 0;
}

E: http://acm.hdu.edu.cn/showproblem.php?pid=1213

并查集维护一下,最后统计维护了几颗树就行。

以下zm代码(:D)

#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;

int pr[1017];

int f(int i){ 
    return i==pr[i]?i:pr[i]=f(pr[i]);
}
void u(int x,int y){ 
    pr[f(x)]=f(y);
}


int main(){
	int T;scanf("%d",&T);
	while(T--){
		int ans=0,n,m,x,y;
		scanf("%d%d",&n,&m);
		for(int i=0;i<=n;++i) pr[i]=i;
		for(int i=0;i<m;++i){
			scanf("%d%d",&x,&y);
			if(f(x)!=f(y)) u(x,y);
		}
		for(int i=1;i<=n;++i){  //求树的棵数
			if(pr[i]==i) ans++;
		}
		printf("%d\n",ans);
	}
    
    return    0;
}

F:http://acm.hdu.edu.cn/showproblem.php?pid=2066

将草儿家和草儿家旁边的城市连一条边,边权为0,跑一遍单源最短路,答案就是min(d[想去的地方])。

以下zm代码(:D)

#include<cstdio>
#include<queue>
#include<set>
#include<vector>
#include<cstring>
#include<algorithm>
using namespace std;

const int INF=0x3f3f3f3f;
const int Mn=1e3+17;
set<int> d; //存想去的城市

struct S{ //优先队列节点
	int v,l;
	S(){}
	S(int xx,int yy):v(xx),l(yy){}
	bool operator <(const S &r)const{
		return l>r.l;
	}
};
struct Edge{ //图节点
	int v,l;
	Edge(int xx,int yy):v(xx),l(yy){}
};
int n,m,c;
bool vis[Mn];
int dis[Mn];
vector<Edge>  e[Mn];
int dij(int s){
	int minn=INF;
	memset(vis,false,sizeof(vis));
	for(int i=1;i<=n;++i) dis[i]=INF;dis[s]=0;
	priority_queue<S> q;while(!q.empty()) q.pop();
	q.push(S(s,0));
	S tmp;
	while(!q.empty()){
		tmp=q.top();q.pop();
		int u=tmp.v;
		if(vis[u]) continue;
		vis[u]=true;
		for(int i=0;i<(int)e[u].size();++i){
			int v=e[tmp.v][i].v,c=e[tmp.v][i].l;
			if(!vis[v]&&dis[v]>dis[u]+c){
				dis[v]=dis[u]+c;
				if(dis[v]<minn&&d.find(v)!=d.end()){  //更新答案
					// printf("v=%d,dis=%d\n",v,dis[v]);
					minn=dis[v];
				}
				q.push(S(v,dis[v]));
			}
		}
	}
	return minn;
}

int team[Mn];
int main(){
	int t,near,D,u,v,len;
	while(~scanf("%d%d%d",&t,&near,&D)){
		for(int i=0;i<=n;++i) e[i].clear();
		d.clear();
		for(int i=0;i<t;++i){
			scanf("%d%d%d",&u,&v,&len);
			e[u].push_back(Edge(v,len));
			e[v].push_back(Edge(u,len));
			n=max(max(n,u),v);
		}
		for(int i=0;i<near;++i){ //草儿家和草儿家旁边的城市连边
			int ne;scanf("%d",&ne);
			e[0].push_back(Edge(ne,0));
		}
		for(int i=0;i<D;++i){
			int want;scanf("%d",&want);
			d.insert(want);
		}
		printf("%d\n",dij(0));
		
	}
	return	0;
}

 

G:https://codeforces.com/contest/237/problem/C

先筛素数,然后统计前缀素数个数。

因为L变大,要符合题意的xi变少,且前缀区间变大,所以满足单调性,直接二分L。

/*   Author : Rshs
 *   Data : 2019-09-09-19.50
 */
#include<bits/stdc++.h>
using namespace std;
#define FI first
#define SE second
#define LL long long
#define MP make_pair
#define PII pair<int,int>
#define SZ(a) (int)a.size()
const double pai = acos(-1);
const LL mod = 1e9+7;
const int MX = 1e6+5;
int pi[MX],pa[MX];int a,b,k;
void pppp(){
    pi[1]=1;
    for(int i=2;i<MX;i++) {
        if(pi[i])continue;
        for(int j=i*2;j<MX;j=j+i) pi[j]=1;
    }
    for(int i=1;i<MX;i++) pa[i]=pa[i-1]+(pi[i]==0);
}
bool check(int l){ 
    for(int i=a;i<=b-l+1;i++)
        if(pa[i+l-1]-pa[i-1]<k) return 0;
    return 1;
}
void Main(int avg){
    cin>>a>>b>>k;int ans=-1,l=1,r=b-a+1;
    while(l<=r){
        int mid=(l+r)/2;
        if(check(mid)) ans=mid,r=mid-1;
        else l=mid+1;
    }
    cout<<ans<<'\n';
}
int main(){
    pppp();
    int cas=1;for(int i=1;i<=cas;i++)Main(i);
    return 0;
}

H:https://codeforces.com/problemset/problem/1118/F1

先将树从一个节点拎起来,dfs每一个节点作为根的子树。

如果子树包含所有的蓝色节点且没有红色节点,或者包含所有红且没有蓝就可以割出来这个子树作为一个答案。

统计满足上述的子树个数即可。

#include<bits/stdc++.h>
using namespace std;
#define LL long long
#define mod 1000000007
#define N 300005
/***************************************************************************************************************************************************************************************************/
int n,red,bule,a[N];
vector<int> v[N];
int dp[N][3];
 
int dfs(int root,int per,int c){
	if(a[root]==c)  dp[root][c]++;
	if(v[root].size()==1) return dp[root][c];
	for(int i=0;i<v[root].size();i++){
		if(v[root][i]==per) continue;
		dp[root][c]+=dfs(v[root][i],root,c);
	}
	return dp[root][c];
}
 
int main(){
	cin>>n;
 
	for(int i=1;i<=n;i++){
		scanf("%d",&a[i]);
		if(a[i]==1) red++;
		if(a[i]==2) bule++;
	}
	for(int i=1;i<=n-1;i++){
		int vv,uu;
		scanf("%d%d",&vv,&uu);
		v[vv].push_back(uu);
		v[uu].push_back(vv);
	}
	if(n==2) {
        cout<<1;
        return 0;
	}
	for(int i=1;i<=n;i++){
        if(v[i].size()>1){
            dfs(i,-1,1);
            dfs(i,-1,2);
            break;
        }
	}
	int ans=0;
	for(int i=1;i<=n;i++){
		if(dp[i][1]==red&&dp[i][2]==0) ans++;
		if(dp[i][1]==0&&dp[i][2]==bule) ans++;
	}
	cout<<ans;
    return 0;
}

 

I:

定义dp[i][j][k],

k==0时,表示到(i,j)时,2累计有几个。

k==1时,表示到(i,j)时,5累计有几个。

答案就是min(dp[n][n][0],dp[n][n][1])。

最后用一个数组记录一下前驱,就可以反向输出路径。

注意输入有0,小心死循环,而且答案为0

/*   Author : Rshs
 *   Data : 2019-09-09-20.50
 */
#include<bits/stdc++.h>
using namespace std;
#define FI first
#define SE second
#define LL long long
#define MP make_pair
#define PII pair<int,int>
#define SZ(a) (int)a.size()
const double pai = acos(-1);
const LL mod = 1e9+7;
const int MX = 1e6+5;
int mp[1005][1005];
int dp[1005][1005][2];
int pa[1005][1005][2];
char go[2]={'D','R'};
vector<char>v;
void Main(int avg){
    int n;cin>>n;
    for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)scanf("%d",&mp[i][j]);
    for(int i=0;i<=n;i++)for(int j=0;j<2;j++)dp[i][0][j]=INT_MAX,dp[0][i][j]=INT_MAX;
    int c=0,d=0,e=mp[1][1],f=mp[1][1];
    while(e%2==0)e/=2,c++;
    while(f%5==0)f/=5,d++;
    dp[1][1][0]=c;dp[1][1][1]=d;
    int ans=INT_MAX;PII an;
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++){
            if(i==1&&j==1)continue;
            int c=0,d=0,e=mp[i][j],f=mp[i][j];
            if(e!=0){
                while(e%2==0)e/=2,c++;
                while(f%5==0)f/=5,d++;
            }
            else ans=1,an=MP(j,i);
            if(dp[i-1][j][0]>dp[i][j-1][0])dp[i][j][0]=dp[i][j-1][0]+c,pa[i][j][0]=1;
            else dp[i][j][0]=dp[i-1][j][0]+c,pa[i][j][0]=0;
            if(dp[i-1][j][1]>dp[i][j-1][1])dp[i][j][1]=dp[i][j-1][1]+d,pa[i][j][1]=1;
            else dp[i][j][1]=dp[i-1][j][1]+d,pa[i][j][1]=0;
        }
    }
    int x=n,y=n,z;
    if(dp[n][n][0]<dp[n][n][1])z=0;
    else z=1;
    int now=min(dp[n][n][0],dp[n][n][1]);
    if(now>ans){ //有0
        cout<<ans<<endl;
        for(int i=1;i<an.FI;i++) cout<<'R';
        for(int i=1;i<an.SE;i++) cout<<'D';
        for(int i=1;i<=n-an.FI;i++) cout<<'R';
        for(int i=1;i<=n-an.SE;i++) cout<<'D';
        return ;
    }
    cout<<now<<endl;
    for(int i=1;i<=2*n-2;i++){
        v.push_back(go[pa[x][y][z]]);
        if(pa[x][y][z]==0) x--;
        else y--;
    }
    reverse(v.begin(),v.end());
    for(auto i:v)cout<<i;
}
int main(){
    int cas=1;for(int i=1;i<=cas;i++)Main(i);
    return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值