zoukankan      html  css  js  c++  java
  • 2017 多校联合训练 2 题解

    Problem 1002

    这个Hash好难……其实要用到抽屉原理。

    这道题当时做出的队伍很少。

    我们取出1000*1000矩阵的所有8*8的矩阵,放到一个map里面。

    然后我们去大矩阵里分块去找这些map里存过的东西……如果找到了那就有了答案。

    也就是说根据原来map里存下的信息判断位置即可。

    因为大矩阵是完全随机的,所以冲突概率很小。

    #include <bits/stdc++.h>
    
    using namespace std;
    
    #define rep(i, a, b)	for (int i(a); i <= (b); ++i)
    #define dec(i, a, b)	for (int i(a); i >= (b); --i)
    #define fi		first
    #define se		second
    
    
    typedef long long LL;
    typedef pair <int, int> PII;
    
    const int N = 1e3 + 10;
    
    int T, flag, ca = 0;
    char s[N][N];
    unordered_map <LL, PII> mp;
    
    
    inline unsigned sfr(unsigned h, unsigned x) {
    	return h >> x;
    }
    int f(LL i, LL j) {
    	LL w = i * 1000000ll + j;
    	int h = 0;
    	for(int k = 0; k < 5; ++k) {
    		h += (int) ((w >> (8 * k)) & 255);
    		h += (h << 10);
    		h ^= sfr(h, 6);
    	}
    	h += h << 3;
    	h ^= sfr(h, 11);
    	h += h << 15;
    	return sfr(h, 27) & 1;
    }
    
    
    int main(){
    
    	scanf("%d", &T);
    	while (T--){
    		rep(i, 1, 1e3) scanf("%s", s[i] + 1);
    		mp.clear();
    		rep(i, 1, 992){
    			rep(j, 1, 992){
    				LL tmp = 0;
    				rep(k, 0, 7){
    					rep(l, 0, 7){
    						tmp <<= 1;
    						tmp |= (s[i + k][j + l] == '1');
    					}
    				}
    
    				mp[tmp] = PII(i, j);
    			}
    		}
    
    		flag = 1;
    		for (int i = 1; i <= 1e6 && flag; i += 984){
    			for (int j = 1; j <= 1e6 && flag; j += 984){
    				LL tmp = 0;
    				rep(k, 0, 7){
    					rep(l, 0, 7){
    						tmp <<= 1;
    						tmp |=  f(i + k, j + l);
    					}
    				}
    
    				if (mp.find(tmp) != mp.end()){
    					PII ans = mp[tmp];
    					flag = 0;
    					printf("Case #%d :%d %d
    ", ++ca, i - ans.fi + 1, j - ans.se + 1);
    				}
    			}
    		}
    	}
    
    	return 0;
    }
    

    Problem 1003

    这道题其实很简单……

    我们对b数组升序排序,显然要从前面开始取。

    做的时候维护后缀最大值,那么就可以O(1)知道原a数列的要取的数了。

    因为从前面开始取,这样之后生成的数也就越大,对整个局面肯定更有利。

    #include <bits/stdc++.h>
    
    using namespace std;
    
    #define rep(i, a, b)    for (int i(a); i <= (b); ++i)
    #define dec(i, a, b)    for (int i(a); i >= (b); --i)
    
    typedef long long LL;
    
    const int N  = 250010;
    const LL mod = 1e9 + 7;
    
    int b[N], n;
    LL a[N], c[N], d[N], ans;
    
    int main(){
    
    	while (~scanf("%d", &n)){
    		rep(i, 1, n) scanf("%lld", a + i);
    		rep(i, 1, n) scanf("%d", b + i);
    
    		sort(b + 1, b + n + 1);
    		ans = 0;
    
    		rep(i, 1, n) c[i] = a[i] - (LL)i;
    		d[n] = c[n];
    		dec(i, n - 1, 1) d[i] = max(d[i + 1], c[i]);
    
    		LL now = -1e10;
    
    		rep(i, 1, n){
    			LL cnt = max(d[b[i]], now);
    			ans = (ans + cnt) % mod;
    			now = max(now, cnt - i - n);
    		}
    
    		printf("%lld
    ", ans);
    
    
    	}
    	return 0;
    }
    

    Problem 1004

    Problem 1005

    Problem 1006

    通过打表找规律 

    发现当n为偶数时,答案为2*(4^((n+1)/2)-1)*(2^n-1)^(m-2)

    当n为奇数时,较复杂,还要减去一个数,当然减去的那个数也有规律

    最后快速幂+乘法逆元即可

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<cstdlib>
    #include<algorithm>
    #include<cstring>
    #include<string>
    #include<vector>
    #include<map>
    #include<set>
    #include<queue>
    using namespace std;
    typedef long long ll;
    const ll mod=1e9+7;
    ll n,m;
    ll pow_mod(ll a,ll b)
    {
        ll ans=1;
        while (b)
        {
            if (b&1) ans=ans*a%mod;
            b>>=1;
            a=a*a%mod;
        }
        return ans;
    }
    int main()
    {
        int _;
        scanf("%d",&_);
        while (_--)
        {
            scanf("%lld%lld",&n,&m);
            if (m==1)
            {
                puts("1");
                continue;
            }
            ll p=(n+1)/2;
            ll fs=pow_mod(4ll,p);
            fs=(fs-1+mod)%mod;
            fs=fs*pow_mod(3,mod-2)%mod;
            if (n%2==0) fs=(fs*2)%mod;
            //cout<<fs<<endl;
            if (m==2)
            {
                printf("%lld
    ",fs);
                continue;
            }
            ll g=(pow_mod(2ll,n)-1+mod)%mod;
            if (n&1)
            {
                p--;
                ll jian=pow_mod(4,p);
                jian=((jian-1)+mod)%mod;
                jian=jian*2%mod;
                jian=jian*pow_mod(3,mod-2)%mod;
                ll times=m-2;
                ll xx=(g-1+mod)%mod;
                ll yy=jian;
                ll nfs=(fs*xx-yy+mod)%mod;
                ll ans=nfs*pow_mod(g,times)%mod;
                ans=(ans+yy)%mod;
                ans=ans*pow_mod(xx,mod-2)%mod;
                printf("%lld
    ",ans);
            }
            else
            {
                ll times=m-2;
                ll ans=fs*pow_mod(g,times)%mod;
                printf("%lld
    ",ans);
            }
        }
        return 0;
    }
    View Code

    Problem 1008

    每个数先单独算出期望然后相加

    这里设置数量为13为临界点

    数量小于13的数用容斥做

    数量大于13的数,用全部的矩阵个数减去全不含的矩阵个数

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<cstdlib>
    #include<algorithm>
    #include<cstring>
    #include<string>
    #include<vector>
    #include<map>
    #include<set>
    #include<queue>
    using namespace std;
    int _,n,m;
    int w[105][105],c[105][105];
    int fg[10010],a[105],b[105];
    vector<pair<int,int>> s[10010];
    int calc(int x)
    {
        int ans=0;
        int i,j;
        for (i=1;i<=n;i++)
        {
            int tmp,tot=0,sum=0;
            for (j=1;j<=m;j++)
            {
                if (w[i][j]!=x)
                    c[i][j]=c[i-1][j]+1;
                else
                    c[i][j]=0;
                tmp=1;
                while (tot&&a[tot]>=c[i][j])
                {
                    tmp+=b[tot];
                    sum-=a[tot]*b[tot];
                    tot--;
                }
                tot++;
                a[tot]=c[i][j];
                b[tot]=tmp;
                sum+=a[tot]*b[tot];
                ans+=sum;
            }
        }
        return ans;
    }
    int calc2(int x)
    {
        int siz=s[x].size();
        int tot=0;
        int i,j;
        for (i=1;i<(1<<siz);i++)
        {
            bool flag=false;
            int p1=n+500,p2=-1,p3=m+500,p4=-1;
            for (j=0;j<siz;j++)
            {
                if (i>>j&1)
                {
                    flag=1-flag;
                    p1=min(p1,s[x][j].first);
                    p2=max(p2,s[x][j].first);
                    p3=min(p3,s[x][j].second);
                    p4=max(p4,s[x][j].second);
                }
            }
            if (flag)
                tot+=p1*(n-p2+1)*p3*(m-p4+1);
            else
                tot-=p1*(n-p2+1)*p3*(m-p4+1);
        }
        return tot;
    }
    int main()
    {
        scanf("%d",&_);
        while (_--)
        {
            scanf("%d%d",&n,&m);
            int i,j;
            for (i=1;i<=n;i++)
                for (j=1;j<=m;j++)
                    scanf("%d",&w[i][j]);
            int tot=0;
            memset(fg,0,sizeof(fg));
            for (i=1;i<=n;i++)
                for (j=1;j<=m;j++)
                {
                    if (fg[w[i][j]]) continue;
                    fg[w[i][j]]=++tot;
                }
            for (i=1;i<=tot;i++)
                s[i].clear();
            for (i=1;i<=n;i++)
                for (j=1;j<=m;j++)
                {
                    w[i][j]=fg[w[i][j]];
                    s[w[i][j]].push_back({i,j});
                }
            double ans=0;
            int zans=n*(n+1)*m*(m+1)/4;
            for (i=1;i<=tot;i++)
            {
                if (s[i].size()>13)
                    ans+=(zans-calc(i))*1.0/zans;
                else
                    ans+=calc2(i)*1.0/zans;
            }
            printf("%.9f
    ",ans);
        }
        return 0;
    }
    View Code

    Problem 1009

    令F[i]表示是i的倍数时的方案数

    可通过处理前缀和

    然后再通过莫比乌斯反演算出答案

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 const int inf=(1<<30)-1;
     4 const int maxn=100010;
     5 #define REP(i,n) for(int i=(0);i<(n);i++)
     6 #define FOR(i,j,n) for(int i=(j);i<=(n);i++)
     7 typedef long long ll;
     8 bool vis[maxn];  
     9 int p[maxn];  
    10 int cnt;  
    11 int g[maxn],u[maxn]; 
    12 int n;
    13 int a[maxn];
    14 int F[maxn];
    15 const int Mo=1e9+7;
    16 int pow(int a,int b,int c)
    17 {
    18     int ans=1;
    19     while(b)
    20     {
    21         if(b&1) ans=1ll*ans*a%c;
    22         a=1ll*a*a%c;
    23         b>>=1;
    24     }
    25     return ans;
    26 }
    27 void Init()  
    28 {  
    29     memset(vis,0,sizeof(vis));  
    30     u[1] = 1;  
    31     cnt = 0;  
    32     for(int i=2;i<maxn-5;i++)  
    33     {  
    34         if(!vis[i])  
    35         {  
    36             p[cnt++] = i;  
    37             u[i] = -1;    
    38         }  
    39         for(int j=0;j<cnt&&i*p[j]<maxn-5;j++)  
    40         {  
    41             vis[i*p[j]] = 1;  
    42             if(i%p[j])  
    43             {  
    44                 u[i*p[j]] = -u[i];  
    45             }  
    46             else  
    47             {  
    48                 u[i*p[j]] = 0;   
    49                 break;  
    50             }  
    51         }  
    52     }   
    53 }  
    54 int main()
    55 {
    56     Init();
    57     int T;scanf("%d",&T);
    58     int Cas=0;
    59     while(T--)
    60     {
    61         scanf("%d",&n);
    62         ll ans=1;
    63         int mn=1e5;
    64         memset(a,0,sizeof(a));
    65         memset(F,0,sizeof(F));
    66         for(int i=1;i<=n;i++) {
    67             int x;scanf("%d",&x);
    68             ans=ans*x%Mo;
    69             a[x]++;
    70         }
    71         for(int i=1;i<=mn;i++)
    72         a[i]+=a[i-1];
    73         for(int i=1;i<=mn;i++) 
    74         if(!a[i-1]) 
    75         {
    76             F[i]=1;
    77             for(int j=1;i*j<=mn;j++)
    78             F[i]=1ll*F[i]*pow(j,a[min(i*(j+1)-1,mn)]-a[i*j-1],Mo)%Mo;
    79         }
    80         ll tmp=0;
    81         for(int i=1;i<=mn;i++)
    82         {
    83             tmp=(tmp+1ll*u[i]*F[i]%Mo)%Mo;
    84         }
    85         ans=(ans-tmp+Mo)%Mo;
    86         printf("Case #%d: %lld
    ",++Cas,ans);
    87     }
    88     return 0;
    89 }
    View Code

    Problem 1011

    这个题思路很明显。

    正多边形肯定只有正方形。

    那么枚举一下就可以了。

    #include <bits/stdc++.h>
    
    using namespace std;
    
    #define rep(i, a, b)	for (int i(a); i <= (b); ++i)
    #define dec(i, a, b)	for (int i(a); i >= (b); --i)
    
    typedef long long LL;
    
    const int N = 603;
    
    int f[N][N];
    int n;
    int ans;
    
    struct Point{
    	int x, y;
    } p[N];
    
    int solve(Point a, Point b){
    	int x = a.x - b.x;
    	int y = a.y - b.y;
    	int ret = 0;
    	if (a.x + y >= 0 && a.y >= x && b.x + y >= 0 && b.y >= x && f[a.x + y][a.y - x] && f[b.x + y][b.y - x]) ++ret;
    	if (a.x >= y && a.y + x >= 0 && b.x >= y && b.y + x >= 0 && f[a.x - y][a.y + x] && f[b.x - y][b.y + x]) ++ret;
    	return ret;
    }
    
    
    int main(){
    
    	while (~scanf("%d", &n)){
    		memset(f, 0, sizeof f);
    		rep(i, 1, n){
    			int x, y;
    			scanf("%d%d", &x, &y);
    			x += 100;
    			y += 100;
    			p[i].x = x;
    			p[i].y = y;
    			f[x][y] = 1;
    		}
    
    		ans = 0;
    		rep(i, 1, n - 1)
    			rep(j, i + 1, n)
    				ans += solve(p[i], p[j]);
    
    		printf("%d
    ", ans / 4);
    	}
    
    	return 0;
    }
    
  • 相关阅读:
    adb shell am pm 用法
    HTML的属性和css基础
    HTML的实际演练2
    HTML的实际演练1
    HTML的标签简介
    HTML的基础知识
    Python之 ---成员修饰符
    Python基础之-----------函数
    Python之-------基础数据类型
    Python之内置函数
  • 原文地址:https://www.cnblogs.com/cxhscst2/p/7441880.html
Copyright © 2011-2022 走看看