zoukankan      html  css  js  c++  java
  • 2020hdu多校第六场比赛及补题

    1009 Divisibility

    题意搞半天才搞懂,把一个词翻译了一下,原来是命题的意思,我以为是一个定义。。

    还是队友告诉我我才理解的题意

    就是一个命题:如果任意一个b进制数,如果它的每位数加起来能被 x 整除,那么它也可以被 x 整除

    就比如任意一个10进制数,如果它的每一位数加起来能被 3 整除,那么它就能被 3 整除,命题为真

    但任意一个10进制数,如果它的每一位数加起来能被4整除,它不一定能被4整除,命题就为假

    为什么b=10时,x=3时,会有这个性质呢

    这是因为10≡1(mod3),100≡1(mod3),1000≡1(mod3)....,46374≡(40000+6000+300+70+4)≡(4+6+3+7+4) (mod3)

    (这个原理我很早以前就知道的)

    显而易见,就是任意一个数左移一位后要同余它本身,左移一位就相当于乘以b,也就是要满足b≡1(mod x)

    #include<iostream>
    #include<algorithm>
    using namespace std;
    int main()
    {
    	int T;
    	long long b,x;
    	cin>>T;
    	while(T--){
    		cin>>b>>x;
    		if((b-1)%x==0) cout<<"T"<<endl;
    		else cout<<"F"<<endl;
    	}
    	return 0;
     } 
    

      

    1002 Little Rabbit's Equation

    进制模拟题,感觉有点麻烦的模拟,还好队友帮我过了这题,强

    #include <bits/stdc++.h>
    using namespace std;
    #define int long long
    // const int MAXN = ;
    // const int MOD = ;
    // const int INF = ;
    // const double eps = ;
    // const int DIRX[] = {};
    // const int DIRY[] = {};
    string str;
    char op;
    string num[5];
    int dci[5];
    
    void getnum()
    {
        int cnt = 1;
        num[1] = "";
        num[2] = "";
        num[3] = "";
        for (int i = 0; i < str.length(); ++i)
        {
            if (str[i] == '=')
            {
                cnt++;
                continue;
            }
            else if (str[i] == '+' || str[i] == '-' 
                    || str[i] == '*' || str[i] == '/')
            {
                cnt++;
                op = str[i];
                continue;
            }
            else
            {
                if (str[i] >= '0' && str[i] <= '9')
                    num[cnt] += (char)(str[i] - '0' + 1);
                else
                    num[cnt] += (char)(str[i] - 'A' + 11);
            }
        }
        if (op == '-')
        {
            op = '+';
            swap(num[1], num[3]);
        }
        if (op == '/')
        {
            op = '*';
            swap(num[1], num[3]);
        }
    }
    
    int32_t main(void)
    {
        ios::sync_with_stdio(false);
        cin.tie(0); cout.tie(0);
        while (cin >> str)
        {
            getnum();
            bool flg = false;
            for (int i = 2; i <= 16; ++i)
            {
                bool ok = false;
                for (int j = 1; j <= 3; ++j)
                {
                    dci[j] = 0;
                    int tmp = 1;
                    for (int k = num[j].length() - 1; k >= 0; --k)
                    {
                        // cout << (int)num[j][k] << " ";
                        if (num[j][k] - 1 >= i)
                        {
                            ok = true;
                            break;
                        }
                        dci[j] += (num[j][k] - 1) * tmp;
                        tmp *= i;
                    }
                    if (ok)
                        break;
                }
                // cout << dci[1] << " " << dci[2] << " " << dci[3] << endl;
                if (ok)
                    continue;
                if (!ok && op == '+')
                {
                    if (dci[1] + dci[2] == dci[3])
                    {
                        flg = true;
                        // cout << dci[1] << "+" << dci[2] << "=" << dci[3] << endl;
                        cout << i << endl;
                    }
                }
                if (!ok && op == '*')
                {
                    if (dci[1] * dci[2] == dci[3])
                    {
                        flg = true;
                        // cout << dci[1] << "*" << dci[2] << "=" << dci[3] << endl;
                        cout << i << endl;
                    }
                }
                if (flg)
                    break;
            }
            if (!flg)
                cout << -1 << endl;
        }
        return 0;
    }
    

      

    1001 Road To The 3rd Building

    有 n 个数,要在[1,n]里任选一个区间,区间的价值=区间内所有数之和 / 区间长度,求价值的期望是多少

    思路:求每个数对最终价值的期望的贡献

    假设有五个数,

    若选择的区间长度为5,这五个数各自贡献的区间数为 1 1 1 1 1

    若选择的区间长度为4,这五个数各自贡献的区间数为 1 2 2 2 1

    若选择的区间长度为3,这五个数各自贡献的区间数为 1 2 3 2 1

    若选择的区间长度为2,这五个数各自贡献的区间数为 1 2 2 2 1

    若选择的区间长度为1,这五个数各自贡献的区间数为 1 1 1 1 1

    就是这个规律

    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    using namespace std;
    const int MAXN = 2e5+7;
    const long long MOD = 1e9+7;
    long long s[MAXN];
    long long th[MAXN];
    long long inv[MAXN];
    
    long long qpow(long long n,long long p){
    	long long ret = 1;
        for (; p; p >>= 1, n = n * n % MOD)
            if (p & 1)
                ret = ret * n % MOD;
        return ret;
    }
    long long mod_inv(long long a) {
        return qpow(a,MOD - 2);
    }
    void pre(){
    	inv[1] = 1;
        for (int i = 2; i <= 2e5; ++i)
            inv[i] = (MOD - MOD / i) * inv[MOD % i] % MOD;
        for(int i = 1;i <= 2e5; i++){
        	th[i] = (th[i-1] + inv[i]) % MOD;
        }
    }
    int main()
    {
    	int T, n;
    	pre();
    	cin >> T;
    	while(T--){
    		cin >> n;
    		for(int i = 1;i <= n;i++){
    			scanf("%lld",&s[i]);
    		}
    		long long fz = 0, fm;
    		long long tt = 0;
    		for(int i = 1;i * 2 <= n;i++){
    			s[i] += s[n-i+1];
    			s[i] %= MOD;
    			tt += th[n-i+1] - th[i-1];
    			tt = (tt % MOD + MOD) % MOD;
    			fz = (fz + s[i] * tt) % MOD;
    		}
    		if(n % 2){
    			tt += inv[n/2+1];
    			tt = (tt % MOD + MOD) % MOD;
    			fz = (fz + s[n/2+1] * tt) % MOD;
    		}
    		fm = (long long)n * ((long long)n+1) / 2 % MOD;//n没有强制转换成long long啊啊 
    		long long ans = fz * mod_inv(fm) % MOD;
    		cout<<ans<<endl;
    	}
    	return 0;
    } 
    

      

    n没有强制转换成long long wa了挺久qwq

    1006 A Very Easy Graph Problem

    给n个点,m条边,每个点有0,1两种状态,要求所有0点到所有1点的最短路的长度之和

    给的这m条边满足第 i 条边的长度为2^i

    根据边长度的性质,可以知道如果A点连了长度为2,4,8,16的边到B,又连了条直接从A到B的边,但这边的长度为32,不能为最短路

    推出一个结论,后面加的边不可能更新已有的最短路,这个边就忽略掉

    这样就像一个并查集一样,把这个图变成若干棵树,然后我就在这些树上进行树形dp

    然后我写了个dfs就MLE了...

    直到比赛结束我还是MLE

    现在才发现原来我并查集写炸了,死循环了。。。。

    然后并查集改好了,还是wa了,手推样例才发现,我那树形dp的方法是错的,要直接dfs一遍每条边的贡献就是这条边的长度*(其一端0点数*另一端1点数+另一端0点数*其一端1点数)

    终于过了xd

    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    #include<vector>
    using namespace std;
    const int MAXN = 1e5+7;
    const int MAXM = 2e5+7; 
    const long long MOD = 1e9+7;
    int a[MAXN];
    long long llo[MAXM];
    
    struct EDGE{
    	int to, w ,next;
    }edge[MAXN*2];
    int head[MAXN],tot;
    
    void add(int u,int v,int w){
    	tot++;
    	edge[tot].to = v;
    	edge[tot].w = w;
    	edge[tot].next = head[u];
    	head[u] = tot;
    }
    
    int n,m;
    long long ans;
    
    int par[MAXN];
    int find(int x){
        if(par[x] == x) return x;
        return par[x] = find(par[x]);
    }
    
    void pre(){
        llo[0] = 1;
        for(int i = 1;i <= 2e5;i++){
            llo[i] = llo[i-1] << 1;
            llo[i] %= MOD;
        }
    }
    
    int son0[MAXN],son1[MAXN];
    long long edg[MAXN]; 
    void dfs(int st,int f){
        son0[st] = son1[st] = 0;
        if(a[st] == 0) son0[st]++;
        else son1[st]++;
        for(int i = head[st];i ;i = edge[i].next){
            int po = edge[i].to;
            if(po == f) continue;
            long long lo = edge[i].w;
            lo = llo[lo];
            edg[po] = lo;
            dfs(po,st);
            son0[st] += son0[po];
            son1[st] += son1[po];
        }
    }
    
    int main()
    {
    	//freopen("1.in","r",stdin);
        int T;
        pre();
        cin >> T;
        int u,v;
        while(T--){
            cin >> n >> m;
            ans = 0;
            tot = 0;
            for(int i = 1;i <= n; i++) {        
                scanf("%d",&a[i]);
                par[i] = i;
                head[i] = 0;
            }
            for(int i = 1;i <= m; i++) {
                scanf("%d%d",&u,&v);
                int fu = find(u), fv = find(v);
                if(fu == fv) continue;
                else{
                    par[fu] = fv;
                    add(u,v,i);
                    add(v,u,i);
                }
            }
            long long res;
            for(int i = 1;i <= n;i++){
                if(par[i] == i) dfs(i,0);  
            }
            for(int i = 1;i <= n;i++){
            	if(find(i)!=i){//不能写成if(par[i]!-=i)因为par[i]并不一定直接连到根节点! 
            		long long ct = 0;
            		ct = 
    				(long long)son1[i] * (  (long long)son0[par[i]] - (long long)son0[i]  ) + 
    				(long long)son0[i] * (  (long long)son1[par[i]] - (long long)son1[i]  ) ;
    				ans += edg[i] * ct;
    				ans %= MOD;
    			}
    		}
            cout << ans << endl;
         }
        return 0;
    }
    

      

  • 相关阅读:
    一句话评论设计模式六大原则
    keystore和truststore
    对于纯Java项目,JVM 各个类加载器的加载目标是什么?
    Keytool 使用总结
    饥饿的消费者(Hungry Consumer)模型
    javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: No trusted c
    如何判断对象已死?
    JMX 管理
    通过 jstat gcutil 来学习JVM 内存分配策略与 GC 发生时机
    程序员也应该有点艺术范儿,不要把“老年代”叫成“Old Generation”
  • 原文地址:https://www.cnblogs.com/ruanbaitql/p/13560987.html
Copyright © 2011-2022 走看看