写完代码就去吃饺子|The 10th Henan Polytechnic University Programming Contest

河南理工大学第十届校赛

很久没有组队打比赛了,好吧应该说很久没有写题了,
三个人一起玩果然比一个人玩有趣多了。。。
前100分钟过了4题,中途挂机100分钟也不知道什么原因,可能是因为到饭点太饿了?,最后100分钟一人开一题差点冲到榜首也太刺激了吧!
是一次愉快的游戏体验。
下周去农大参加邀请赛,希望能和今天一样快乐~


今天是冬至,别忘记吃饺子!


写完代码就去吃饺子|The 10th Henan Polytechnic University Programming Contest_第1张图片

题解和代码

A. Dong Zhi

A题地址
题意:输出"Let's eat dumplings",这句话
思路:看标题肯定签到了,但是hpu前5分钟好卡,网速拼不过。

#include
using namespace std;

int main(){
    cout<<"Let's eat dumplings"<


B. The flower

B题地址
题意:统计字符串中 出现次数>2的,长度为T的子串。从小到大按字典序输出子串。
思路:用unorder_map统计子串出现的次数。substr(i,k)截取字符串。

#include
#include
using namespace std;

string s;
string flower = "flower";
int k;
unordered_mapmp;
vector ans;


int main(){
    cin>>s>>k;
    int len = s.length();
    string temp;
    for(int i=0;i+k<=len;i++){
        temp = s.substr(i,k);
        mp[temp]++;
    }
    unordered_map:: iterator it = mp.begin();
    while(it != mp.end()){
        if(it->second > 2) ans.push_back(it->first);
        it++;
    }
    sort(ans.begin(),ans.end());
    printf("%d\n",ans.size());
    for(int i=0;i


C. Xor Path

C题地址
题意:一颗树,Q次查询,求两个结点最小的异或和。
思路:求最近公共祖先,dfs求每个结点到根节点1的路径异或和,lca优化,复杂度qlogn

#include
using namespace std;

typedef long long ll;
const int maxn = 1e6+100;
vector g[maxn];
int pre[maxn],a[maxn],parent[maxn],f[maxn][30],depth[maxn];
ll bit[30];

//初始化bit数组:求2的i次幂 
void init(){
    bit[0] = 1;
    for(int i=1;i<=29;i++){
        bit[i] = (bit[i-1]<<1);
    }
}

void dfs(int u,int par){
    depth[u] = depth[par] + 1;
    f[u][0] = par;
    for(int i=1;bit[i]<=depth[u];i++) f[u][i] = f[f[u][i-1]][i-1];
    for(int v:g[u]){
        if(v!=par) dfs(v,u);
    }
}

//求x和y的最近公共祖先 
int lca(int x,int y){
    if(depth[x] < depth[y]) swap(x,y);
    for(int i=29;i>=0;i--){
        if(depth[x] - depth[y] >= bit[i]) x = f[x][i];
    }
    if(x == y) return x;
    for(int i=29;i>=0;i--){
        if(depth[x] >= (1<>n;
    for(int i=1;i<=n;i++) cin>>a[i];
    init();
    //建图 邻接表
    for(int i=0;i<=n;i++) g[i].clear();
    for(int i=1;i<=n-1;i++){
        cin>>u>>v;
        g[u].push_back(v);
        g[v].push_back(u);
    }
    dfs(1,0);
    //dfs计算从根节点到每个结点的异或和
    DFS1(1,0);
    int x,y;
    cin>>q;
    while(q--){
        cin>>x>>y;
        int c = lca(x,y); //求x,y的最近公共祖先 
        int f = parent[c]; //求最近公共祖先的父节点 这里再求一次父节点的原因是: 消除祖先的父节点到根节点这段路径(异或了2次)的异或 
        cout<<(pre[x]^pre[y]^pre[f]^pre[c])<

D. LaunchPad

D题地址
题意:翻转pad,每次翻转第x一整行和第y一整列,求Q次后最终翻转为亮面的个数
思路:队友过的。。似乎开两个一维数组,一个统计行,一个统计列,判断奇偶就可以了

#include
#include
#include
#include
#include
using namespace std;
int mp[1005][1005];
int main(){
    int m,n;cin>>n>>m;
    int q;cin>>q;
    int visX[1005];
    int visY[1005];
    memset(visX,0,sizeof(visX));
    memset(visY,0,sizeof(visY));
    while(q--){
        int x,y;
        cin>>x>>y;
        visX[x]++;
        visY[y]++;
        mp[x][y]++;
    }
    int ans = 0;
    for(int i = 1;i<=n;i++){
        for(int j = 1;j<=m;j++){
            if((visX[i]+visY[j]+mp[i][j])%2!=0){
                ans++;
            }
        }
    }
    cout<


E. Morse code

E题地址
题意:给一个字符串,找最长可以匹配莫斯码成功的字母长度。
思路:这。。队友过的,我题目还没看完,他就过了。等等??看了看他代码,也太秀了。

#include
#include
#include
#include
#include
#include
#include
#include
#include

using namespace std;

typedef long long ll;
const int maxn =2e5+10;
const ll N=1e9+7;

bool flag;
int main()
{
    int t;
    cin >> t;
    while(t--)
    {
        string s;
        cin >> s;
        ll ans=s.size()/2; //这样就行了嘛??
        cout << ans << endl;
    }
    return 0;
}


F. For language

F题地址
题意:计算时间复杂度。
思路:一行一行读,看第一个输入的字符串是什么就,按什么来

#include
using namespace std;

typedef long long ll;
const ll mod = 1e9+7;
int n;

ll get(string x,string y){
    ll xx = 0;
    for(int i=0;i>n;
    bool develop = 0;
    ll ans = 0;
    ll value = 0;
    for(int line=1;line<=n;line++){
        string first;
        cin>>first;
        if(first == "begin"){
            develop = 1;
            value = -1;
        }else if(first == "for" && develop==1){
            string a;
            cin>>a;
            string num1;
            cin>>num1;
            string num2;
            cin>>num2;
            ll cur = get(num1,num2)%mod;
            //判断等于0的情况
            if(value == -1) value = 1;
            value = (value * cur) % mod;
        }else if(first == "end"){
            develop = 0;
            if(value != -1)
                ans = (ans + value)%mod;
        }
    }
    cout<


G. Puzzle

G题地址
题意:累加一个数每一位上的cycle值,其中1, 2, 3, 5, 7 have 0 cycle, 4, 6, 9 have 1 cycle and 8 has 2 cycles.
思路:看懂样例,就可以直接做了

#include
using namespace std;

typedef long long ll;
int t;

int a[10] = {1,0,0,0,1,0,1,0,2,1};

int main(){
    cin>>t;
    while(t--){
        ll x;
        cin>>x;
        ll temp = x;
        int ans = 0;
        while(temp){
            ans+=a[temp%10];
            temp/=10;
        }
        cout<


H. Triangle tower

H题地址
不是动态规划,队友过的,组合数,和杨辉三角有关。
放上队友在地铁上画的两张图。。。

#include
#include
#include
#include
#include
using namespace std;
const int mod = 1e9+7;
const int maxn = 1e5+5;
typedef long long ll;
ll c[maxn];//组合数 1 1e5
ll fac[maxn];
ll inv[maxn];
ll qpow(long long a,long long b)
{
    ll ans=1;
    ll k=a;
    while(b)
    {
        if(b&1)ans=ans*k%mod;
        k=k*k%mod;
        b>>=1;
    }
    return (ans+mod)%mod;
}
void init(){
    long long i;
    fac[0]=1;
    inv[0]=1;
    fac[1]=1;
    inv[1]=1;
    for (i=2;i>t;
    init();
    while(t--){
        int m,n;
        cin>>n>>m;
        ll ans; 
        if(m%2 == 1){
            m = m/2+1;
            m--;
            n--;
            int t = n - m;
            ans = C(n,m);
        }
        else{
            m = m/2;
            m--,n-=2;
            int t = n - m;
            //cout<


I. Kingdom of Mathematics

I题地址
没做,还不会。

J. HPU's birthday

J题地址
题意:给一个数n,求这个数n的二进制字符串,再把这个二进制字符串循环拼接n次,求最终i,j,k能组成110的组数
思路:我做了半天,思路错了;队友想到可以遍历最终拼接后的字符串,每次出现0,就统计前面有多少个1,选出两个1就可以了。比如前面出现了x个1,就计算C(x,2)
所以最后用了 前缀和,AC了,但是不要忘了开longlong,乘法会溢出!!wa了7次就这个原因。。怪自己很久没写代码细节都忘了。

#include
using namespace std;

typedef long long ll;
const ll mod = 1e9+7;
//const ll maxn = 2e6+10;
const int maxn = 1700000;
ll C[maxn];
int t;
ll n;
vector vec;
vector v;
vector ans;

void cov(ll x){
    vec.clear(); 
    v.clear();
    if(x == 0) {
        v.push_back(0);
        return;
    }
    while(x){
        vec.push_back(x%2);
        x = x/2;
    }
    for(int i=vec.size()-1;i>=0;i--) v.push_back(vec[i]);
}

void init(){
    for(ll i=1;i<=maxn;i++){
        C[i] = ((i*(i-1))/2)%mod;
    }
}

ll a[maxn];

int main(){
    init();
    cin>>t;
    while(t--){
        cin>>n;
        cov(n);
        ans.clear();
        ans.push_back(0);
        for(ll i=1;i<=n;i++){
            for(int j=0;j


K. Max Sum

K题地址
思路:两颗线段树:tp维护最小前缀和,tn维护最小后缀和
要计算[L,R]上的最大区间和,(其中 L<=i,R<=i+ki,L<=R)
只需要求出区间[i-ki-1,i-1]的最小前缀和 和 区间[i+1,i+ki+1]的最小后缀和
数组总和减去这两部分的值就是第i个位置上的最大wonderful interval

#include
using namespace std;
#define ll long long
const int maxn=1000000+10;
const int INF=0x3f3f3f3f;
int a[maxn];
ll pre[maxn],nxt[maxn];
int k[maxn];
int N;

//线段树单点更新区间求和
struct Tree{
    ll x[maxn];
    //初始化 
    void init(int x){
        N=1;
        while(N<=x*2) N*=2;
    }
    //单点更新 
    void update(int k,int q){
        k+=N-1;
        x[k]=q;
        while(k){
            k=(k-1)/2;
            x[k]=min(x[k*2+1],x[k*2+2]);
        }
    }
    //区间查询 
    ll query(int a,int b,int l,int r,int k){
        if(r=1;i--){
        sum+=a[i];
        tn.update(i,sum);
    }
    //i从1~n  sum为数组总和     定义的最大区间值 就=sum-最小前缀-最小后缀
    ll ans=0;
    for(int i=1;i<=n;i++){
        ans+=sum;
        ans-=tp.query(max(i-k[i]-1,0),max(i-1,0),0,N-1,0);
        ans-=tn.query(min(i+1,n+1),min(i+k[i]+1,n+1),0,N-1,0);
    }
    printf("%lld\n",ans);
    return 0;
}

L. Restore Expressions

思路:两个始自终除第一个数a,b外其它全取1,另表达式右端=0,计算使a,b恢复到正数的最大次数。

你可能感兴趣的:(写完代码就去吃饺子|The 10th Henan Polytechnic University Programming Contest)