ICPC焦作站(EF)+思维+树上dp

Posted 钟钟终

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ICPC焦作站(EF)+思维+树上dp相关的知识,希望对你有一定的参考价值。

这场比赛依旧是三道题,E其实比我们出的D难一点,但确实在能力范围之内,出了就保底铜牌了,出的快的话说不定有银。策略很重要

E. Resistors in Parallel

大数+打表找规律。
最后得出公式:R=素数乘积/该素数的因子之和
由于范围达到了10的100次幂,有一次感受到python的便捷,但用的太少,不如c++顺手。
1.素数筛得出素数。2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47……
2.重点在于素数因子之和的处理。(分子各个质因子+1)的乘积。

# -*- coding: utf-8 -*-
prime=[]
def is_prime(n):
    i=2
    vis=[0 for i in range(n+5)]
    while i*i<=n:
        if vis[i]==0:
            for j in range(i*2,n,i):
                vis[j]=1
        i+=1
    for i in range(n+5):
        if i==0 or i==1 : continue
        if vis[i]==0:
            prime.append(i)
def gcd(a,b):
    return a if b==0 else gcd(b,a%b)

is_prime(100000)
for T in range(int(input())):
    n=int(input())
    sum1=1
    sum2=1
    i=0
    while 1:
        if sum1*prime[i]>n:
            break
        sum1*=prime[i]
        sum2*=(prime[i]+1)
        i+=1
    g=gcd(sum1,sum2)
    #print(sum1,sum2,sum2)
    sum1//=g
    sum2//=g
    print(f"sum1/sum2")

E2. Divisible Numbers (hard version)

思路:
k1和k2是a、b乘积数的因子,因此得出公式:x*y=k*a*b=kk*k1*k2
分解a和b的质因子,再去深搜k1、k2对于各个质因子的所取个数
最后比较x和y的值小于等于c和d,即为找到满足要求的数。

#include <bits/stdc++.h>
#define int long long
#define ios cin.tie(0),cout.tie(0),ios::sync_with_stdio(0);
#define endl '\\n'
#define ULL unsigned long long
#define down 0.996
using namespace std;
const double eps=1e-8;
const double inf=1e18;
const int mod=998244353;
const int P=131;
const int N=7e5+5;
int a,b,c,d,ansx,ansy,flag;
map<int,int>mp;
vector<pair<int,int>>e;
int qpow(int x,int y)

    int res=1;
    while(y)
    
        if(y&1) res*=x;x*=x;y>>=1;
    
    return res;

void demcopse(int x)

    for(int i=2;i*i<=x;i++)
        if(x%i==0)
            while(x%i==0) mp[i]++,x/=i;
    if(x>1) mp[x]++;

void dfs(int num,int k1,int k2)

    if(flag) return;
    if(num==e.size())
    
        int sx=(a/k1+1)*k1;
        int sy=(b/k2+1)*k2;
        if(sx<=c&&sy<=d)
            flag=1,ansx=sx,ansy=sy;
        return;
    
    int x=e[num].first,y=e[num].second,pw=0,tmp=1;
    pw=qpow(x,y);
    for(int i=0;i<=y;i++)
    
        dfs(num+1,k1*tmp,k2*(pw/tmp));
        tmp*=x;
    

void solve()

    mp.clear();e.clear();
    ansx=ansy=flag=0;
    cin>>a>>b>>c>>d;
    demcopse(a);demcopse(b);
    for(auto x:mp) e.push_back(x);
    dfs(0,1,1);
    if(flag)
        cout<<ansx<<" "<<ansy<<endl;
    else
        cout<<"-1 -1"<<endl;

signed main()


    ios;
    int T;cin>>T;
    while(T--)
        solve();
    return 0;



D. Paths on the Tree

题意:找到k条简单路径,每个点都有一个权值p[i]c[i]为经过该点的次数,在满足一个分支节点的孩子|c[i]-c[j]|<=1的情况下,要求各个点 的c[i]*p[i]权值最大。
思路:
1.在满足题目限制条件的情况下,可看出对于一个结点的孩子来说,会有p(k%sz)个结点被多经过一次,因此我们需要找到权值较大的节点路径进行分配。
2.设计dp状态:f[u][0]表示以u为根节点,没有被分配额外一次路径所获得的最大权值;
f[u][1]表示以u为根节点,被分配额外一次路径所获得的最大权值.
3.对每一层的孩子节点可进行降序排列存到vector数组中。

#include <bits/stdc++.h>
#define int long long
#define ios cin.tie(0),cout.tie(0),ios::sync_with_stdio(0);
#define endl '\\n'
#define ULL unsigned long long
#define down 0.996
using namespace std;
const double eps=1e-8;
const double inf=1e18;
const int mod=998244353;
const int P=131;
const int N=2e6+5;
int n,k,p[N],dp[N][2];
vector<int>e[N];
void dfs(int u,int k)

    dp[u][0]=p[u]*k;dp[u][1]=(k+1)*p[u];
    vector<int>son;
    for(int v:e[u]) son.push_back(v);
    if(!son.size()) return;
    int x=son.size();
    int k1=k/x,k2=k%x;
    vector<pair<int,int>>tp;
    for(int v:son) dfs(v,k1);
    for(int v:son) tp.push_back(dp[v][1]-dp[v][0],v);
    sort(tp.begin(),tp.end(),[&](pair<int,int> &p,pair<int,int> &q)
       return p.first>q.first;
    );
    for(int i=0;i<tp.size();i++)
    
        int v=tp[i].second;
        if(i<k2) dp[u][0]+=dp[v][1];
        else dp[u][0]+=dp[v][0];
        if(i<=k2) dp[u][1]+=dp[v][1];
        else dp[u][1]+=dp[v][0];
    

void solve()

    cin>>n>>k;
    for(int i=0;i<=n;i++) e[i].clear();
    for(int i=2;i<=n;i++)
    
        int x;cin>>x;e[x].push_back(i);
    
    for(int i=1;i<=n;i++) cin>>p[i];
    dfs(1,k);
    cout<<dp[1][0]<<endl;

signed main()

    ios;
    int T;cin>>T;
    while(T--)
        solve();
    return 0;



D. Problem with Random Tests

略有取巧的做法,使用了bitset进行位运算,猜测前50位必会随机产生一个0

#include <bits/stdc++.h>
#define int long long
#define ios cin.tie(0),cout.tie(0),ios::sync_with_stdio(0);
#define endl '\\n'
#define ULL unsigned long long
#define down 0.996
using namespace std;
const double eps=1e-8;
const double inf=1e18;
const int mod=998244353;
const int P=131;
const int N=1e6+5;
int n;
string s;

void solve()

    cin>>n>>s;
    int g=0;
    while(g<n&&s[g]!='1') g++;
    if(g>=n)
    
        cout<<0<<endl;return;
    
    s=s.substr(g,n);
    bitset<N>b1(s),b2(s);
    string ans=b1.to_string();
    for(int i=1;i<=50;i++)
        ans=max(ans,(b1|(b2>>i)).to_string());
    g=0;
    while(g<ans.length()&&ans[g]!='1') g++;
    cout<<ans.substr(g)<<endl;

signed main()

    ios;
    //int T;cin>>T;
    //while(T--)
        solve();
    return 0;



F. Honeycomb

思路:这题输出的时候好像不能用ios,不然会wa 1.
1.使用bfs从起点搜索到终点,到达终点后判断退出,输出最小值。
2.对于走过的点可使用特殊字符进行标记,这样就不会走回头路了。找对6个方向记录到数组中即可。

#include <bits/stdc++.h>
#define int long long
#define ios cin.tie(0),cout.tie(0),ios::sync_with_stdio(0);
#define endl '\\n'
#define ULL unsigned long long
#define down 0.996
using namespace std;
const double eps=1e-8;
const double inf=1e18;
const int mod=998244353;
const int P=131;
const int N=1e6+5;
int r,c,sx,sy,tx,ty,row,col;
char mp[4005][6005];
int len[4005];
int dx[6]=-2,2,-2,2,-4,4;
int dy[6]=-6,-6,6,6,0,0;
queue<pair<pair<int,int>,int>>q;
bool check(int x,int xx,int y,int yy)

    int kx=(x+xx)/2,ky=(y+yy)/2;
    if(xx>=1&&xx<=row&&yy>=1&&yy<=len[xx]&&mp[xx][yy]!='@'&&mp[kx][ky]!='-'&&mp[kx][ky]!='/'&&mp[kx][ky]!='\\\\')
        return 1;
    return 0;

void solve()

    while(!q.empty()) q.pop();
    cin>>r>>c;
    row=r*4+3,col=c*6+3;
    for(int i=1;i<=row;i++)
    
        len[i]=0;
        for(int j=0;j<=col;j++) mp[i][j]=' ';
    
    2018ACM-ICPC焦作站E题Resistors in Parallel

ACM-ICPC 2018 焦作赛区网络预赛 B. Mathematical Curse << DP

2018ICPC 焦作 B - Ultraman vs. Aodzilla and Bodzilla(贪心,思维)

2018ICPC 焦作 B - Ultraman vs. Aodzilla and Bodzilla(贪心,思维)

ACM-ICPC 2018 焦作赛区网络预赛 B. Mathematical Curse << DP

ACM-ICPC 2018 焦作赛区网络预赛 Transport Ship