HDU多校第六场

1001:简单的求贡献的题目,分段求解最后求出期望即可

代码:

#include<bits/stdc++.h>
using namespace std;
#define p 1000000007
#define INF 0x3f3f3f3f
#define pi 3.141592654
typedef long long ll;
const int N = 2e5+5;
ll sum[N],inv[N];
ll a[N];
int main(){
    inv[1]=1,sum[1] = 1,sum[0] = 0;
    for(int i=2;i<=N;i++){
        inv[i]=(p-p/i)*inv[p%i]%p;
        sum[i]= (sum[i-1] + inv[i])%p;
    }
    int n,t;scanf("%d",&t);
    while(t--){
        scanf("%d",&n);
        ll ans = 0,cnt = n,tem = sum[n];
        for(int i =1 ; i<= n ; i++){
            scanf("%lld",&a[i]);
            if(i > 1){
                tem = (tem + sum[n-i+1] - sum[i-1]+ p)%p;
            }
            ans = (a[i] * tem %p  + ans )%p;
        }
        ans = (ans*inv[n]%p)*inv[n+1]%p *2 %p;
        printf("%lld\n",ans);
    }
    return 0;
}

1002:暴力,注意开ll

队友代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
char ch[101];
char sh[101];
char mh[101];
int main(){
    while(scanf("%s",ch+1)!=EOF){
        int t=strlen(ch+1);
        int ma=-5;
        for(int i=1;i<=t;i++){
            char c=ch[i];
            if(c>='0'&&c<='9')
                c-='0';
            if(c>='A'&&c<='F')
                c=c-'A'+10;
                if(c>=0&&c<=15)
            ma=max(ma,(int)c);
        }
        int k=-1;
      // printf("ma=%d\n",ma);
        for(ll i=max(ma+1,2);i<=16;i++){
            ll shu1=0,f=0,q=-1,shu2=0,shu3=0;
            for(int j=1;j<=t;j++){
                 char c=ch[j];
                if(c>='0'&&c<='9')
                    c-='0';
                else if(c>='A'&&c<='F')
                    c=c-'A'+10;
                else if(c=='+')
                    q=1;
                else if(c=='-')
                    q=2;
                else if(c=='*')
                    q=3;
                else if(c=='/')
                    q=4;
                if(q!=-1&&f==0){
                    f=1;
                    continue;
                }
                if(c=='='){
                    f=2;
                    continue;
                }
                ll y=c;
                if(f==0)
                shu1=shu1*i+y;
                else if(f==1){
                    shu2=shu2*i+y;
                }
                else if(f==2){
                     shu3=shu3*i+y;
                }
            }
           // printf("i=%d,shu1=%lld,shu2=%lld,shu3=%lld,q=%lld\n",i,shu1,shu2,shu3,q);
            if(q==1){
                if(shu1+shu2==shu3){
                    k=i;
                    break;
                }
            }
            if(q==2){
                if(shu1-shu2==shu3){
                    k=i;
                    break;
                }
            }
            if(q==3){
                if(shu1*shu2==shu3){
                    k=i;
                    break;
                }
            }
            if(q==4){
                if(shu1/shu2==shu3&&shu1%shu2==0){
                    k=i;
                    break;
                }
            }
        }
        printf("%d\n",k);
    }
}

1005

题意:给一个序列为1145141919的无限循环串,已知一个N,输出最小的前n位数,在前n位数中任意的加上()+ *使得前n位数构成的式子值为N

思路:在这里插入图片描述

代码:

/// dp[i][j][v1+v2]=dp[i][mid][v1]与dp[mid+1][j][v2]。
/// dp[i][j][v1"v2]=dp[i][mid][v1]与dp[mid+1][j][v2]dp[i][j][v1"v2]=dp[i][mid][v1]与dp[mid+1][j][v2]。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 5005;
int num[15] = {0,1,1,4,5,1,4,1,9,1,9,1,1,4};
int dp[13][13][N];///dp[i][j][val]表示val在i到j区间可以生成
int ans[N],t,n;
int main(){
    for(int i = 1 ; i <= 12 ;i++){
        int tem = 0;
        for(int j =  i ; j <= 12;j++){
            tem = tem * 10 + num[j];///加括号可以形成的数
            if(tem < N) dp[i][j][tem] = 1;
            else break;
        }
    }
    for(int l = 11 ; l >= 1 ; l--){///需要从后往前d,从前往后会造成数值缺失,因为从前往后第一遍扫过去的话,i=1时后面相当于只加了括号,没有进行+*操作
        for(int r = l+1 ; r <= 12 ; r++){
            for(int mid = l; mid < r ; mid++)
            for(int tem = 1; tem <= 5000 ; tem ++){
                if(!dp[l][mid][tem])    continue;///区间[l,mid]无法构成数字tem
                for(int val = 1 ; val <= 5000 ; val++){
                    if(!dp[mid+1][r][val])  continue;///区间[mid+1,r]无法构成数字val
                    if(val + tem < N)   dp[l][r][val+tem] = 1;
                    if(val * tem < N)   dp[l][r][val*tem] = 1;
                }
            }
        }
    }
    for(int i = 12 ; i >= 1 ; i--)
        for(int val = 1 ; val <= 5000 ;val ++)
            if(dp[1][i][val])   ans[val] = i;
    int t;scanf("%d",&t);
    while(t --){
        scanf("%d",&n);
        if(ans[n] > 0)  printf("%d\n",ans[n]);
        else        printf("-1\n");
    }
    return 0;
}

1006

思路:在这里插入图片描述

队友代码:

/*
* @Author: Admin
* @Date:   2020-08-06 13:12:38
* @Last Modified by:   Admin
* @Last Modified time: 2020-08-06 14:21:06
*/
#include <bits/stdc++.h>
using namespace std;
#define pb push_back
#define mp make_pair
#define fi first
#define se second
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> PII;
typedef pair<ll, ll> pll;
const int mod = 1e9 + 7;
const int N = 1e5 + 10;
const int INF = 0x3f3f3f3f;
ll qpow(ll base, ll n){ll ans = 1; while (n){if (n & 1) ans = ans * base % mod; base = base * base % mod; n >>= 1;} return ans;}
ll gcd(ll a, ll b){return b ? gcd(b, a % b) : a;}
int a[N];
int head[N], ver[N << 1], nex[N << 1], tot;
ll edge[N << 1], siz[N][2], num[2], ans;
void add(int u, int v, ll w) {
    ver[++ tot] = v;
    edge[tot] = w;
    nex[tot] = head[u];
    head[u] = tot;
}
void dfs(int u, int fa) {
    siz[u][0] = a[u] ^ 1;
    siz[u][1] = a[u];
    for (int i = head[u]; i; i = nex[i]) {
        int v = ver[i];
        if (v != fa) {
            dfs(v, u);
            ll x = 0;
            ll w = edge[i];
            x = (num[1] - siz[v][1]) * siz[v][0] % mod;
            x = (x + (num[0] - siz[v][0]) * siz[v][1] % mod) % mod;
            ans = (ans + x * w % mod) % mod;
            siz[u][0] += siz[v][0];
            siz[u][1] += siz[v][1];
        }
    }
    return ;
}
int main()
{
    int t;
    cin >> t;
    while (t --) {
        tot = 0;
        ans = 0;
        memset(head, 0, sizeof(head));
        memset(num, 0, sizeof(num));
        int n, m;
        scanf("%d %d", &n, &m);
        for (int i = 1; i <= n; ++ i) {
            scanf("%d", &a[i]);
            ++ num[a[i]];
        }
        ll w = 1;
        for (int i = 1; i <= m; ++ i) {
            int u, v;
            scanf("%d %d", &u, &v);
            if (i < n) {
                w = w * 2 % mod;
                add(u, v, w);
                add(v, u, w);
            }
        }
        dfs(1, -1);
        printf("%lld\n", ans);
    }
    return 0;
}

1009 结论题,注意ll

题意及思路:

在这里插入图片描述

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int main(){
    int t;scanf("%d",&t);
    while(t --){
        ll b, x;
        scanf("%lld %lld", &b, &x);
        if (x == 1) printf("T\n");
        else {
            if (b > x && b % x == 1) printf("T\n");
            else printf("F\n");
        }
    }
    return 0;
}

1010

题意:给一个图,生成树的权值定义为树的所有边求与,问随机生成的生成树的期望。

思路:在这里插入图片描述

代码:

#include<bits/stdc++.h>
using namespace std;
#define mod 998244353
#define INF 0x3f3f3f3f
#define pi 3.141592654
typedef long long ll;
const int N = 2e6+5;
ll qpow(ll base, ll n){
    ll ans = 1;
    while (n){
        if (n & 1)
        ans = (ans%mod) * (base % mod) %mod;
        base = (base%mod) * (base % mod) %mod;
        n >>= 1;
    }
    return ans;
}
ll f[207][207];
ll gauss (int n) {
    ll ans = 1 ;
    for (int i = 1; i < n; i ++) {
        for (int j = i + 1; j < n; j ++) {
            while (f[j][i]) {
                ll t = f[i][i] / f[j][i] ;
                for (int k = i; k < n; k ++)
                    f[i][k] = (f[i][k] - t * f[j][k] + mod) % mod ;
                swap (f[i], f[j]) ;
                ans = -ans ;
            }
        }
        ans = (ans * f[i][i]) % mod ;
    }
    return (ans + mod) % mod ;
}
ll u[40007],v[40007],w[40007];
int main(){
    int t;scanf("%d",&t);
    while(t--){
        int m,n;
        scanf("%d %d",&n,&m);
        for(int i = 1 ; i <= m ; i++){
            scanf("%lld %lld %lld",&u[i],&v[i],&w[i]);
            f[u[i]][u[i]]++ ; f[v[i]][v[i]]++;
            f[u[i]][v[i]]-- ; f[v[i]][u[i]]--;
        }
        ll sum = gauss(n);
       // printf("%lld\n",sum);
        sum = qpow(sum,mod-2);
        ll ans = 0,base = 1;
        for(int i = 0 ; i <= 30 ; i++){
            memset(f,0,sizeof(f));
            for(int j = 1 ; j <= m ; j++){
                if(w[j]&base){
                    f[u[j]][u[j]]++ ; f[v[j]][v[j]]++;
                    f[u[j]][v[j]]-- ; f[v[j]][u[j]]--;
                }
            }
            ans = (ans + gauss(n)*base%mod) % mod;
            base *= 2;
        }
        ans = ans*sum%mod;
        printf("%lld\n",ans);
    }
    return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值