2018-2019 ACM-ICPC, Asia Dhaka Regional Contest 寒假自训第九场

前些天拜年咕了,今天成功被fcy带飞了

B.Counting Inversion

fcy代码:

#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define ll long long
using namespace std;
const int Mod=998244353;
struct in{
    ll num,sum,cnt[10];
    in(){num=sum=0; memset(cnt,0,sizeof(cnt)); }
}dp[16][10];
int v[20],q[20],tot,vis[16][10];
in dfs(int pos,int st,int lim)
{
    if(!lim&&vis[pos][st]) return dp[pos][st];
    if(pos==1) {
        in res;  res.num=1;//res.cnt[st]=1;
        return res;
    }
    int up=9; in res,tmp; if(lim) up=q[pos-1];
    rep(i,0,up){
        tmp=dfs(pos-1,i,lim&&i==up);
        res.sum+=tmp.sum;
        rep(j,i+1,9) res.sum+=tmp.cnt[j];
        rep(j,0,9) res.cnt[j]+=tmp.cnt[j];
        res.cnt[i]+=tmp.num;
        res.num+=tmp.num;
    }
    vis[pos][st]=1;
    return dp[pos][st]=res;
}
ll cal(ll x)
{
    if(x<10) return 0;
    tot=0; ll ans=0;
    while(x) q[++tot]=x%10,x/=10;
    memset(dp,0,sizeof(dp));
    memset(vis,0,sizeof(vis));
    rep(i,1,tot){
        ll up=9; if(i==tot) up=q[tot];
        rep(j,1,up){
             in tmp=dfs(i,j,(i==tot)&&(j==q[tot]));
             ans+=tmp.sum;
             rep(k,j+1,9) ans+=1LL*tmp.cnt[k];
        }
    }
    return ans;
}
int main()
{
    v[1]=1; rep(i,2,18) v[i]=(ll)v[i-1]*10%Mod;
    ll L,R;  int T,Ca=0; scanf("%d",&T);
    while(T--){
       scanf("%lld%lld",&L,&R);
       printf("Case %d: %lld\n",++Ca,cal(R)-cal(L-1));
    }
    return 0;
}
/*
5
1 9
1 100
50 60
23 2343
345 99373
*/

C.Divisors of the Divisors of An Integer

fcy代码:

#include<bits/stdc++.h>
#define ll long long
#define rep(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
const int maxn=1000010;
const int Mod=1e7+7;
int a[maxn],N,p[maxn],vis[maxn],cnt;ll ans=1;
int solve(int p)
{
    int tN=N,res=0;
    while(tN) {
        res+=tN/p;
        if(res>Mod) res-=Mod;
        tN/=p;
    } return res;
}
int get(int p)
{
    if(p&1) return 1LL*(p+1)/2*p%Mod;
    return 1LL*p/2*(p+1)%Mod;
}
int main()
{
    rep(i,2,1000000){
        if(!vis[i]) p[++cnt]=i;
        for(int j=1;j<=cnt&&p[j]*i<=1000000;j++){
            vis[p[j]*i]=1;
            if(i%p[j]==0) break;
        }
    }
    while(~scanf("%d",&N)&N){
       ans=1;
       rep(i,2,N) {
          if(!vis[i]) a[i]=solve(i);
       }
       rep(i,2,N){
         if(a[i])
           ans=(ll)ans*get(a[i]+1)%Mod;
       }
       printf("%lld\n",ans);
    }
    return 0;
}

E. Helping the HR

题意:规定白班必须要9.30之前到公司,上班时间最少8小时,晚班必须12.30之前到公司,上班时间最少9小时,且计算上班时间最早从8.30开始,如果一个人上班迟到或者早退,会被扣分,一个月扣3分以上会被发邮件,给出n天上班时间,判断最后的状态。

水题。

#include<bits/stdc++.h>
using namespace std;
char str[30];
int main()
{
	int n,s=17*1800,D=19*1800,E=25*1800;
	while(~scanf("%d",&n)&&n)
	{
		int cnt=0;
		for(int cas=0;cas<n;cas++)
		{
			int S=0,T=0,tot=0,pre=0,p=3600;
			scanf("%s",str);
			int len=strlen(str);
			for(int i=2;i<len;i++)
			{
				if(str[i]!=':'&&i!=len-1)pre=pre*10+str[i]-'0';
				else
				{
					if(i==len-1)pre=pre*10+str[i]-'0';
					tot++;
					if(tot<=3)
					{
						S+=pre*p;
						if(tot==3)p=3600;
						else p/=60;
					}
					else T+=pre*p,p/=60;
					pre=0;
				}
			}
			int flag=0;
			if(str[0]=='D'&&S>D)flag=1;
			if(str[0]=='E'&&S>E)flag=1;
			int res=T-max(s,S);
			if(str[0]=='D'&&res<8*3600)flag=1;
			if(str[0]=='E'&&res<9*3600)flag=1;
			cnt+=flag;			
		}
		if(!cnt)puts("All OK");
		else if(cnt<=3)printf("%d Point(s) Deducted\n",cnt);
		else puts("Issue Show Cause Letter");
	}		
}
/*
3
D:8:30:00:17:30:20
D:9:30:01:17:30:20
E:11:30:01:20:31:00
3
D:8:30:00:16:30:00
D:9:30:00:17:30:20
E:11:30:01:20:31:00
3
D:8:30:00:17:30:20
D:9:30:01:17:30:20
E:11:30:01:20:00:00
4
D:8:00:00:16:15:20
D:9:30:01:17:30:00
E:11:30:01:20:00:00
E:11:30:01:20:00:00
*/

F .Path Intersection

题意:给出k条a到b的路径,求k条路径的公共点。

思路:先树剖,然后k次区间+1,最后查询区间内最小值=k的点的个数即可。

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e4+10;
int id[maxn],dep[maxn],cnt;
int top[maxn],size[maxn],f[maxn],son[maxn];
vector<int>G[maxn];
int tag[maxn*4],mx[maxn*4],mn[maxn*4];
void dfs1(int u,int fa,int deep)
{
	f[u]=fa;
	size[u]=1;
	dep[u]=deep;
	son[u]=0;
	for(int i=0;i<G[u].size();i++)
	{
		int v=G[u][i];
		if(v==fa)continue;
		dfs1(v,u,deep+1);
		size[u]+=size[v];
		if(size[v]>size[son[u]])son[u]=v;
	}
}
void dfs2(int u,int root)
{
	top[u]=root;
	id[u]=++cnt;
	if(son[u])dfs2(son[u],root);
	for(int i=0;i<G[u].size();i++)
	{
		int v=G[u][i];
		if(v==f[u]||v==son[u])continue;
		dfs2(v,v);
	}
}
void pushdown(int o,int ls,int rs,int l,int m,int r)
{
	if(tag[o]!=0&&l!=r)
	{
		mx[ls]+=tag[o],mx[rs]+=tag[o];
		mn[ls]+=tag[o],mn[rs]+=tag[o];
		tag[ls]+=tag[o],tag[rs]+=tag[o];
		tag[o]=0;
	}	
}
void update(int o,int l,int r,int ql,int qr,int v)
{	
	int m=(l+r)/2,ls=o*2,rs=o*2+1;
	pushdown(o,ls,rs,l,m,r);
	if(l>=ql&&r<=qr)
	{
		mx[o]+=v,mn[o]+=v,tag[o]+=v;
		return;
	}
	if(ql<=m)update(ls,l,m,ql,qr,v);
	if(qr>m)update(rs,m+1,r,ql,qr,v);
	mx[o]=max(mx[ls],mx[rs]);
	mn[o]=min(mn[ls],mn[rs]);
}
int query(int o,int l,int r,int ql,int qr,int k)
{
	int m=(l+r)/2,ls=o*2,rs=o*2+1,res=0;
	pushdown(o,ls,rs,l,m,r);
	if(mx[o]<k)return 0;
	if(mn[o]==k)return min(r,qr)-max(l,ql)+1;
	if(ql<=m)res+=query(ls,l,m,ql,qr,k);
	if(qr>m)res+=query(rs,m+1,r,ql,qr,k);
	return res;
}
void up_path(int x,int y,int z)
{
	while(top[x]!=top[y])
	{
		if(dep[top[x]]<dep[top[y]])swap(x,y);
		update(1,1,cnt,id[top[x]],id[x],z);
		x=f[top[x]];
	}
	if(id[x]>id[y])swap(x,y);
	update(1,1,cnt,id[x],id[y],z);
}
int qu_path(int x,int y,int z)
{
	int ans=0;
	while(top[x]!=top[y])
	{
		if(dep[top[x]]<dep[top[y]])swap(x,y);
		ans+=query(1,1,cnt,id[top[x]],id[x],z);
		x=f[top[x]];
	}
	if(id[x]>id[y])swap(x,y);
	ans+=query(1,1,cnt,id[x],id[y],z);
	return ans;
}
int a[55],b[55];
int main()
{
	int T,n,k,u,v,q,Case=0;
	scanf("%d",&T);
	while(T--)
	{
		printf("Case %d:\n",++Case);
		scanf("%d",&n);
		for(int i=1;i<=n;i++)G[i].clear();
		for(int i=1;i<n;i++)
		{
			scanf("%d%d",&u,&v);
			G[u].push_back(v);
			G[v].push_back(u);
		}
		cnt=0;
		dfs1(1,0,1);
		dfs2(1,1);
		scanf("%d",&q);
		while(q--)
		{
			scanf("%d",&k);
			for(int i=1;i<=k;i++)
			scanf("%d%d",&a[i],&b[i]),up_path(a[i],b[i],1);
			printf("%d\n",qu_path(a[1],b[1],k));
			for(int i=1;i<=k;i++)up_path(a[i],b[i],-1);
		}		
	}
}
/*
2
6
1 2
2 3
3 4
2 5
2 6
2
2
4 5
3 6
3
4 5
3 1
2 6

2
1 2
1
2
1 1
2 2
*/

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

长沙橘子猫

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值