Regionals 2014 Asia - Bangkok

A.1-n两两相乘能得到多少个不同的数字?
解法:正解还不知道,此题可以直接O(n^2)预处理f[n],询问时查询即可

B.C(n,r), x<=n<=y,0=<r<=n 中奇数个数
解法:
结论:C(n,r)为奇数的充要条件是n&r=r
结论:C(n,r), 0=<r<=n 中奇数个数为 2j 个,j为n的二进制中1的个数
由以上两个结论,可以得到此题的统计方法。先统计 0<=n<=y 的结果
将n表示成二进制,遇到1时讨论此位是1还是0,如果是0,那么后面的位数可以随意填充,因此需要预处理二进制前k位的组合数结果和。如果是1,那么继续往后移动。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <vector>
#include <algorithm>
#include <queue>
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define ll long long
#define ul unsigned long long
#define N maxn
using namespace std;

ll l,r;

ll Power(ll a,ll b){
    ll ans=1ll;
    for(ll i=0;i<b;i++) ans=ans*a;
    return ans;
}

ll cal(ll x){
    ll ans=0,xi=1,xx=x,i=0;
    while(xx){
        if(xx&1){
            ans*=2; xi*=2;
            ans+=Power(3,i);
        }
        i++,xx/=2;
    }
    return ans;
}

int main(){
    //freopen("a.txt","r",stdin);
    while(scanf("%lld%lld",&l,&r)!=EOF){
        if(l==0&&r==0) break;
        ll ansa=cal(r+1),ansb=cal(l);
        printf("%llu\n",ansa-ansb);
    }
    return 0;
}

E. k!(1<=k<=n) 中10的幂次不同的个数
解法:n/5即为答案。
拓展:x的幂次不同的个数为n/p,p为x中最大的素因子

F.求矩阵中的最长路和最短路,移动法则是只能向右下方移动
解法:有很明显的移动方向,dp即可解决

G.构造题。重点在通过不等关系判断等式的解。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <vector>
#include <algorithm>
#include <queue>
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define ll long long
#define N maxn
using namespace std;

const int INF = 0x3f3f3f3f;
const int maxn = 1000+10;
int t,n,m;
int a[maxn][maxn],ans[maxn][maxn];

void solve(){
    for(int i=1;i<=n;i+=2){
        for(int j=1;j<=m;j++){
            a[i][j]=a[i][j]-ans[i-1][j-1]-ans[i-1][j]-ans[i-1][j+1];
        }
        if(i==n){
            if(a[i][1]>=4) ans[i][1]=1,a[i][1]-=3;
            if(a[i][2]-a[i][1]>=3) ans[i][2]=1,a[i][2]-=3;
            for(int j=3;j<=m;j++){
                if(a[i][j]-a[i][j-1]+ans[i][j-2]>=3) ans[i][j]=1,a[i][j]-=3;
            }
            continue;
        }
        if(a[i][1]>=4) ans[i][1]=1,a[i][1]-=3;
        if(a[i][2]-a[i][1]>=3) ans[i][2]=1,a[i][2]-=3;
        if(a[i+1][1]-a[i][1]>=3) ans[i+1][1]=1,a[i+1][1]-=3;
        ans[i+1][2]=a[i][1]-ans[i][1]-ans[i][2]-ans[i+1][1];
        if(ans[i+1][2]==1) a[i+1][2]-=3;
        for(int j=3;j<=m;j++){
            if(a[i][j]-a[i][j-1]+ans[i][j-2]+ans[i+1][j-2]>=3) ans[i][j]=1,a[i][j]-=3;
            ans[i+1][j]=a[i][j-1]-ans[i][j-1]-ans[i][j-2]-ans[i][j]-ans[i+1][j-2]-ans[i+1][j-1];
            if(ans[i+1][j]==1) a[i+1][j]-=3;
        }
    }
}

int main(){
    //freopen("a.txt","r",stdin);
    scanf("%d",&t);
    while(t--){
        scanf("%d%d",&n,&m);
        memset(ans,0,sizeof(ans));
        for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) scanf("%d",&a[i][j]);
        solve();
        for(int i=1;i<=n;i++){
            for(int j=1;j<=m;j++){
                if(ans[i][j]==1) printf("L"); else printf("-");
            }
            printf("\n");
        }
    }
    return 0;
}

H.矩阵被若干加号形式覆盖,每个点有一个覆盖次数,求满足覆盖次数的加号分布。
解法:搜索。每次遇到覆盖一次的位置,将它作为加号中心,找到它的最远边界,作为加号长度,然后继续搜索下一个位置

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <vector>
#include <algorithm>
#include <queue>
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define ll long long
#define N maxn
using namespace std;

const int INF = 0x3f3f3f3f;
const int maxn = 100+10;
int t,n,m;
int ma[maxn][maxn],sum,can[maxn][maxn];
int ans,ansx,ansy;

bool dfs(int i,int j,int sum){
    if(sum==0) return true;
    if(i==n&&j==m) return false;
    if(ans>=9&&sum!=0) return false;
    int x=i,y=j+1;
    if(y>m) x=i+1,y=1;
    if(i!=1&&i!=n&&j!=1&&j!=m&&ma[i][j]==1){
        int c=1;
        while(i>=c&&i+c<=n&&j>=c&&j+c<=m&&ma[i-c][j]>0&&ma[i+c][j]>0&&ma[i][j-c]>0&&ma[i][j+c]>0){
            ma[i-c][j]--,ma[i+c][j]--,ma[i][j-c]--,ma[i][j+c]--; c++; sum-=4;
        }
        c--;
        if(c){
            sum-=1; ma[i][j]=0;
            if(dfs(x,y,sum)){
                ans++;
                if(ansx<i) { ansx=i,ansy=j; }
                else if(ansx==i&&ansy<j) ansy=j;
                return true;
            }
            ma[i][j]=1; sum+=1;
        }
        while(c){
            ma[i-c][j]++,ma[i+c][j]++,ma[i][j-c]++,ma[i][j+c]++; c--; sum+=4;
        }
    }
    return dfs(x,y,sum);
}

int main(){
    //freopen("a.txt","r",stdin);
    scanf("%d",&t);
    while(t--){
        scanf("%d%d",&n,&m);
        sum=0;
        memset(can,0,sizeof(can));
        for(int i=1;i<=n;i++) for(int j=1;j<=m;j++){
            scanf("%d",&ma[i][j]);
            sum+=ma[i][j];
            if(i!=1&&i!=n&&j!=1&&j!=m){
                if(ma[i][j]==1&&ma[i-1][j]>0&&ma[i+1][j]>0&&ma[i][j-1]>0&&ma[i][j+1]>0) can[i][j]=1;
            }
        }
        ans=0,ansx=-1,ansy=-1;
        dfs(1,1,sum);
        printf("%d\n",ans);
        printf("%d %d\n",ansx,ansy);
    }
    return 0;
}

I.匹配问题,拆点最大流解决。

J.m个定长等间距区间覆盖整个数轴,问1-n中每个点被覆盖1-m次的点个数
解法:定长等间距区间覆盖满足mod的性质。判断一个点是否被一区间覆盖,只要判断该点mod间距是否在该区间内,预处理mod b大于a的区间总和dp[b][a],对于k点只要加上所有的dp[b][k%b]即可

K.每天有一个选择得到一定利润,换选择需要付出代价,求最大利润
解法:简单O(n^3)dp

L.矩阵中每个数字是它的四条相邻边权值之和,矩阵边界权值为0。矩阵中只有一个数字未知,求该数字的值。
解法:求与该格子的曼哈顿距离,奇数加偶数减,结果即为所求

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
['Asia/Aden', 'Asia/Almaty', 'Asia/Amman', 'Asia/Anadyr', 'Asia/Aqtau', 'Asia/Aqtobe', 'Asia/Ashgabat', 'Asia/Ashkhabad', 'Asia/Atyrau', 'Asia/Baghdad', 'Asia/Bahrain', 'Asia/Baku', 'Asia/Bangkok', 'Asia/Barnaul', 'Asia/Beirut', 'Asia/Bishkek', 'Asia/Brunei', 'Asia/Calcutta', 'Asia/Chita', 'Asia/Choibalsan', 'Asia/Chongqing', 'Asia/Chungking', 'Asia/Colombo', 'Asia/Dacca', 'Asia/Damascus', 'Asia/Dhaka', 'Asia/Dili', 'Asia/Dubai', 'Asia/Dushanbe', 'Asia/Famagusta', 'Asia/Gaza', 'Asia/Harbin', 'Asia/Hebron', 'Asia/Ho_Chi_Minh', 'Asia/Hong_Kong', 'Asia/Hovd', 'Asia/Irkutsk', 'Asia/Istanbul', 'Asia/Jakarta', 'Asia/Jayapura', 'Asia/Jerusalem', 'Asia/Kabul', 'Asia/Kamchatka', 'Asia/Karachi', 'Asia/Kashgar', 'Asia/Kathmandu', 'Asia/Katmandu', 'Asia/Khandyga', 'Asia/Kolkata', 'Asia/Krasnoyarsk', 'Asia/Kuala_Lumpur', 'Asia/Kuching', 'Asia/Kuwait', 'Asia/Macao', 'Asia/Macau', 'Asia/Magadan', 'Asia/Makassar', 'Asia/Manila', 'Asia/Muscat', 'Asia/Nicosia', 'Asia/Novokuznetsk', 'Asia/Novosibirsk', 'Asia/Omsk', 'Asia/Oral', 'Asia/Phnom_Penh', 'Asia/Pontianak', 'Asia/Pyongyang', 'Asia/Qatar', 'Asia/Qostanay', 'Asia/Qyzylorda', 'Asia/Rangoon', 'Asia/Riyadh', 'Asia/Saigon', 'Asia/Sakhalin', 'Asia/Samarkand', 'Asia/Seoul', 'Asia/Shanghai', 'Asia/Singapore', 'Asia/Srednekolymsk', 'Asia/Taipei', 'Asia/Tashkent', 'Asia/Tbilisi', 'Asia/Tehran', 'Asia/Tel_Aviv', 'Asia/Thimbu', 'Asia/Thimphu', 'Asia/Tokyo', 'Asia/Tomsk', 'Asia/Ujung_Pandang', 'Asia/Ulaanbaatar', 'Asia/Ulan_Bator', 'Asia/Urumqi', 'Asia/Ust-Nera', 'Asia/Vientiane', 'Asia/Vladivostok', 'Asia/Yakutsk', 'Asia/Yangon', 'Asia/Yekaterinburg', 'Asia/Yerevan']
最新发布
02-07
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值