2018 Multi-University Training Contest 4

hdu 6334 Problem D. Nothing is Impossible

http://acm.hdu.edu.cn/showproblem.php?pid=6335

这道题到最后直接把题解给改到题面上去了。。。

一开始的题面其实是可以的。可能出题人认为这道题应该是水题吧。。

先解释一下为什么要把所有的正确选项(一开始的正确选项是有多个的)都认为是1

因为要保证有人能够全过所谓S这个子集里面的题目。那么你想啊,这是一场考试啊,尽管大家能够互相交流,但是没人知道哪个选项是对的啊。对吧。 比如5 个正确选项,5个错误选项,10个人,每人选不同的选项,确实是会有5个人能够答对,但是啊 你怎么知道谁一定是对的呢,而且还有后面的题目,后面的题目就不能去按照这样的策略去做了。

再讲为什么把正确选项视为1个可以做。比如2道题,数据分别是1 7 和1 3 ,现在我们有64人。那么我们先用64除以(7+1)

得到8,意味着我们把64人分为8组,每一组选一个答案,这样,我最倒霉这8组里面7组跪了,只有一组对了。那么对于下一题,我们用8除以(1+3),意味着,我们把8个人分成4组,每组选一个答案,那么最倒霉这8个人4组里,有3组错了,但有一组是对的。这样一来是不是可以理解了。这样分的话,我们不需要去知道哪些答案是对的。因为肯定有一组第一题是对的,然后这一组面的一小组人在下一组也是对的。这样的话是不是能保证运气最差也能保证至少有人能够全过S这个集合里面的所有题目了。

至于怎么去贪心就很简单了。

#include<bits/stdc++.h>
using namespace std;
#define LL long long int
struct node
{
    int a,b;
}a[111111];
bool cmp(node a,node b)
{
    return a.b<b.b;
}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        int n,m;
        scanf("%d%d",&n,&m);
        for(int i=0;i<n;i++)
        {
            scanf("%d%d",&a[i].a,&a[i].b);
        }
        sort(a,a+n,cmp);
        int ans=0;
        for(int i=0;i<n;i++)
        {
            if(m>a[i].b)
            {
                m/=(a[i].b+1);
                ans++;
            }
            if(!m)break;
        }
        printf("%d\n",ans);

    }
    return 0;
}

 

hdu 6342 Problem K. Expression in Memories

http://acm.hdu.edu.cn/showproblem.php?pid=6342

整体思路就是尽量让问号为1. 只有例如+0?这种需要把?变为符号。

然后弄完后检验一下合法性即可。。

#include<bits/stdc++.h>
using namespace std;
#define LL long long int
char c[505],b[505];
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%s",c);
        int len=strlen(c);
        for(int i=0;i<len;i++)
        {
            b[i]='1';
        }
        int f=-1;
        int flag=1;
        for(int i=0;i<len;i++)
        {
            if(c[i]=='+'||c[i]=='*')
            {
                if(f==-1)
                {
                    flag=0;
                    break;
                }
                f=-1;
            }
            else if(c[i]=='?')
            {
                if(f==0)
                {
                    b[i]='+';
                    f=-1;
                }
                else f=1;
            }
            else if(c[i]=='0')
            {
                if(f==-1)f=0;
                else if(f==0)
                {
                    flag=0;
                    break;
                }
            }
            else
            {
                if(f==0)
                {
                    flag=0;
                    break;
                }
                f=1;
            }
        }
        if(!flag||f==-1)
        {
            printf("IMPOSSIBLE\n");
        }
        else
        {
            for(int i=0;i<len;i++)
            {
                if(c[i]=='?')printf("%c",b[i]);
                else printf("%c",c[i]);
            }
            printf("\n");
        }
    }
    return 0;
}

 

hdu 6343  Problem L. Graph Theory Homework

http://acm.hdu.edu.cn/showproblem.php?pid=6343

开题的时候,队友喊着最短路,果断tle 太帅了

a-b的距离为根号下a和b的差值,仔细举举例子就会发现,如果中间加一个点的话不可能会让路径长度变短。。。

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
const int inf=0x3f3f3f3f;
struct node
{
    int v,w;
};
vector<node>e[N];
int a[N];
int dis[N];
int vis[N];
void spfa()
{
    dis[0]=0;
    vis[0]=1;
    queue<int>Q;
    int u;
    Q.push(0);
    while(!Q.empty())
    {
        u=Q.front();
        Q.pop();
        for(int i=0;i<e[u].size();i++)
        {
            int v=e[u][i].v;
            int w=e[u][i].w;
            if(dis[v]>dis[u]+w)
            {
                dis[v]=dis[u]+w;
                if(!vis[v])
                {
                    Q.push(v);
                    vis[v]=1;
                }
            }
        }
    }
}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        int n;
        scanf("%d",&n);
        for(int i=0;i<n;i++)
        {
            scanf("%d",&a[i]);
        }
        int d=sqrt(abs(a[0]-a[n-1]));
        printf("%d\n",d);
    }
    return 0;
}

 

hdu 6333 Problem B. Harvest of Apples

http://acm.hdu.edu.cn/showproblem.php?pid=6333

通过Snm 可以得到Sn-1m Sn+1m Snm-1 Snm+1 

然后用莫队搞一下

注意mod要用静态变量或者宏定义。

如果超时了 可能是因为你把mod 放在了全局里。。。。

#include<bits/stdc++.h>
#define mod 1000000007 
using namespace std;
struct node{
    long  dow,upp;
    int id;
    int blog;
}q[111111];
bool cp(node x,node y)
{
    if(x.blog==y.blog)return x.dow<y.dow;
    return x.blog<y.blog;
}
long long ss[111111];
long long inv[111111];
long long jl[111111];
long long qpow(long long x,long long cs)
{
    long long ans=1;
    while(cs)
    {
        if(cs&1)ans=ans*x%mod;
        x=x*x%mod;
        cs>>=1;
    }
    return ans;
}
long long C(long long n,long long m)
{
    long long fz=ss[n]%mod;
    long long fm=inv[n-m]%mod*inv[m]%mod;
    fz=(fz*fm)%mod;
    //cout<<n<<" "<<m<<" "<<fz<<endl;
    return fz;
}
int main()
{
    ss[0]=1;
    ss[1]=1;
    for(int i=2;i<=100000;i++)
    {
        ss[i]=(ss[i-1]*i)%mod;
    }

    for(int i=0;i<=100011;i++)
     inv[i]=qpow(ss[i],mod-2);
    int t;
    cin>>t;
    int len=sqrt(100000.0);
    for(int i=0;i<t;i++)
    {
            scanf("%d%d",&q[i].dow,&q[i].upp);
            q[i].id=i;
            q[i].blog=q[i].upp/len;
    }
    sort(q,q+t,cp);
    long long ans=1;
    long long shang=0;
    long long er=qpow(2,mod-2);
    long long xia=1;
    for(int i=0;i<t;i++)
    {
        while(xia<q[i].dow)
        {
            //cout<<"1"<<endl;
            ans=(ans*2-C(xia,shang)+mod)%mod;
            xia++;
        }
        while(shang<q[i].upp)
        {
            //cout<<"2"<<endl;
            shang++;
            ans=(ans+C(xia,shang))%mod;
        }
        while(xia>q[i].dow)
        {
            //cout<<"3"<<endl;
            xia--;
            ans=(ans+C(xia,shang))*er%mod;
        }
        while(shang>q[i].upp)
        {
            //cout<<"4"<<endl;
            ans=(ans-C(xia,shang)+mod)%mod;
            shang--;
        }
        jl[q[i].id]=ans;
    }
        for(int i=0;i<t;i++)
        {
            printf("%lld\n",jl[i]);
        }
    return 0;
}

 

hdu 6341 Problem J. Let Sudoku Rotate

http://acm.hdu.edu.cn/showproblem.php?pid=6341

就是简单的dfs加上一点点的剪枝。。。可恶啊 比赛的时候没看啊。。。。

#include<bits/stdc++.h>
using namespace std;
char a[22][22];
int s[22][22];
int vis[22];
int ans;
int js=0;
bool check(int x,int y)
{
    for(int i=x;i<x+4;i++)
    {
        js++;
        for(int j=0;j<y+4;j++)
        {
            if(vis[s[i][j]]==js)
            return 0;
            vis[s[i][j]]=js;
        }
    }
    for(int i=y;i<y+4;i++)
    {
        js++;
        for(int j=0;j<x+4;j++)
        {
            if(vis[s[j][i]]==js)
            return 0;
            vis[s[j][i]]=js;
        }
    }
    return 1;
}
void zhuan(int x,int y)
{
    int t[4][4];
    for(int i=0;i<4;i++)
    {
        for(int j=0;j<4;j++)
        {
            t[i][j]=s[x+i][y+j];
        }
    }
    for(int i=0;i<4;i++)
    {
        for(int j=0;j<4;j++)
        {
            s[i+x][j+y]=t[3-j][i];
        }
    }
}
void dfs(int x,int y,int cnt)
{
    if(x==4)
    {
        ans=min(cnt,ans);
        return ;
    }
    if(cnt>=ans)
    return ;
    if(y==4)
    {
        dfs(x+1,0,cnt);
    }
    for(int i=0;i<4;i++)
    {
        if(check(x*4,y*4))
        {
            dfs(x,y+1,cnt+i);
        }
        zhuan(x*4,y*4);
    }
}
void wort()
{
    for(int i=0;i<16;i++)
    cin>>a[i];
    for(int i=0;i<16;i++)
    for(int j=0;j<16;j++)
    {
        if(a[i][j]>='0'&&a[i][j]<='9')
        s[i][j]=a[i][j]-'0';
        else s[i][j]=a[i][j]-'A'+10;
    }
    ans=160628;
    dfs(0,0,0);
    cout<<ans<<endl;
}
int main(){
    int t;
    cin>>t;
    while(t--)
    {
        js=0;
        wort();
    }
    return 0;
}

 

hdu 6336 Problem E. Matrix from Arrays

http://acm.hdu.edu.cn/showproblem.php?pid=6336

循环节是2l*2l,预处理2L*2L的矩阵前缀和,那么对于每一个坐标点到原点的面积就可以求了

代码是转的

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const LL     mod = 1e9 + 7;
const int maxn = 101;
int A[maxn];
LL M[maxn][maxn]; 
LL S[maxn][maxn];
int n ,L ;
LL L2;
void init(void){

        n = 4*L;
        L2 = 2*L;
        int cursor = 0;
        for(int i = 0;i < n; ++i ){
            for(int j = 0;j <= i; ++j){
                M[j][i-j] = A[cursor];
                cursor = (cursor+1)% L;
            }
        }
        for(int i = 1;i <= L2; ++i){
             for(int j = 1;j <= L2; ++j){
                     S[i][j] = 0;
                      S[i][j] = S[i-1][j]+S[i][j-1]-S[i-1][j-1]+M[i-1][j-1];
             }
        }     
}

LL solve(LL x,LL y){
    x++,y++;
    LL ans = 0;
    LL xx = x/L2, yy = y/L2;
    LL xxx = x%L2,yyy = y % L2;
    // 整的 
    ans += xx*yy*S[L2][L2];
    // 右边
    ans += xx*S[L2][yyy];
    // 下边
    ans += yy*S[xxx][L2];
    // 角落
    ans += S[xxx][yyy]; 
    return ans;
}

int main()
{
    int T;
    scanf("%d",&T);
    int cursor = 0;
    while(T--) {
        scanf("%d",&L);
        for(int i = 0;i < L; ++i)
          scanf("%d",&A[i]);
      init(); 
      int Q;
      scanf("%d",&Q);
      while(Q--){
        LL  x1,y1,x2,y2;
        scanf("%lld %lld %lld %lld",&x1,&y1,&x2,&y2);
        printf("%lld\n",solve(x2,y2)-solve(x1-1,y2)-solve(x2,y1-1)+solve(x1-1,y1-1));
      }
    }

   return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值