2017多校联合赛1[题解]

hdu6033-hdu6044

I题调不出来了!!!!

哪位dalao带带我啊.......

(坑估计补不完了.....)

A

题意:输入n,输出2n-1的位数

思路:log算一下就好..

贴队友代码:

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;

int main(){
    int n,kase=0;
    while(scanf("%d",&n)==1){
        printf("Case #%d: %d\n",++kase,int(1.0*n*log(2)/log(10)));
    }
}

B

题意:给你一堆字符串,每个字母代表一个数字.求你求出所有字符串转化为十进制后的总和的最大值

思路:贪心而已..细节神烦

贴队友代码

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
char buff[100010];
const int mod=1e9+7;

LL ex[100010];
struct bignum{
    LL A[100010];
    int size;
    int id;
    bool isfirst;
    void init(int x){memset(A,0,sizeof(LL)*(size+1));size=0;id=x;isfirst=0;}
    bool operator <(const bignum &x){
        if (size!=x.size) return size<x.size;
        for (int i=size;i>=0;i--){
            if (A[i]!=x.A[i]) return A[i]<x.A[i];
        }
        return 0;
    }
}k[30];
int main(){
    int n,kase=0;
    ex[0]=1;
    for (int i=1;i<=100000;i++) ex[i]=(ex[i-1]*26)%mod;
    while(scanf("%d",&n)==1){
        for (int i=0;i<30;i++) k[i].init(i);
        for (int i=1;i<=n;i++){
            scanf("%s",buff);
            int len=strlen(buff);
            for (int j=len-1,p=0;j>=0;j--,p++){
                int pos=buff[j]-'a';
                k[pos].A[p]++;
                int pp=p;
                while (k[pos].A[pp]>25){
                    k[pos].A[pp++]-=26;
                    k[pos].A[pp]++;
                }
                k[pos].size=max(k[pos].size,pp);
                if (j==0) k[pos].isfirst=1;
            }
        }
        sort(k,k+26);
        int tmp=0;
        while(tmp<25&&k[tmp].isfirst) tmp++;
        for (int i=tmp;i>0;i--) swap(k[i],k[i-1]);
        LL ans=0;
        #ifdef waterdragon
        for (int i=0;i<26;i++) printf("%c ",k[i].id+'a');
        printf("\n");
        #endif
        for (int i=0;i<26;i++){
            for (int j=0;j<=k[i].size;j++){
                ans=(ans+k[i].A[j]*i*ex[j])%mod;
            }
        }
        printf("Case #%d: %lld\n",++kase,ans);
    }
}

C:留坑

D:留坑

E:留坑

F

题意:有一种函数,f(x)=y其中0<=x<n,0<=y<m

请你求出一共有多少种方案使得f[x]=bf(a[x])

思路:向每个x和a[x]连边,发现可以构成一个循环.

然后我们又发现,如果知道f[x]是多少,那么整个循环是否成立也能知道.

然后,设c[x]=a[x]则a[a[x]]=c[c[x]]

发现这样又能构成一个循环..

于是让每个bi向i连一条边,如果有一个a的循环长度是某个b的循环长度的倍数,那么该循环成立

贴自己代码:

#include <cstdio>
#include <cstring>
#define mod 1000000007 
#define N 1000010
using namespace std;
typedef long long ll;
ll i,j,k,n,m,x,y,t,T,b[N],c[N],d[N],e,ne[N],v[N],p[N];
void dfs(ll x,ll &y){if (v[x])return;v[x]=1;y++;dfs(ne[x],y);}
int main(){
    while (~scanf("%lld%lld",&n,&m)){
        memset(v,0,sizeof v);
        memset(d,0,sizeof d);
        memset(c,0,sizeof c);
        memset(p,0,sizeof p);
        ll ans=0;
        for (i=0;i<n;i++){scanf("%lld",&x);ne[i]=x;}
        for (i=0;i<n;i++)if (!v[i]){ans++;dfs(i,d[ans]);}
        for (i=0;i<m;i++){scanf("%lld",&b[i]);ne[b[i]]=i;}
        memset(v,0,sizeof v);e=0;
        for (i=0;i<m;i++){if (v[i])continue;x=0;if (!v[i])dfs(i,x);if (x==1)e++;else for (j=x;j<=n;j+=x)c[j]+=x;}
        long long ans1=1;
        for (i=1;i<=ans;i++){if (p[d[i]])continue;c[d[i]]+=e;p[d[i]]=1;}
        for (i=1;i<=ans;i++)ans1=(ans1*c[d[i]])%mod;
        printf("Case #%d: ",++T);printf("%lld\n",ans1);
    }
    return 0;
}

G:留坑

H:

题意:给你一种生成序列的方式,问你该序列第i小是多少

思路:stl题,nth_element简直是神器啊,记得从零开始读入数组..这样更快....

代码:

#include <cstdio>
#include <algorithm>
using namespace std;
typedef unsigned uint;
uint A,B,C,n,m,i,j,k,a[10001000],ans[101],x,y,z;
struct data{uint x,id;}b[101];
uint rng61() {
  uint t;
  x ^= x << 16;
  x ^= x >> 5;
  x ^= x << 1;
  t = x;
  x = y;
  y = z;
  z = t ^ x ^ y;
  return z;
}
bool cmp(const data&a,const data&b){return a.x<b.x;}
int main(){
    int T=0;
    while (~scanf("%u%u%u%u%u",&n,&m,&A,&B,&C)){
        x = A, y = B, z = C;
        for (i=0;i<m;i++){scanf("%u",&b[i].x);b[i].id=i;}
        sort(b,b+m,cmp);
        for (i=0;i<n;i++)a[i]=rng61();
        b[m].x=n;
        for (i=m-1;~i;i--){nth_element(a,a+b[i].x,a+b[i+1].x);ans[b[i].id]=a[b[i].x];}
        printf("Case #%d:",++T);for (i=0;i<m;++i)printf(" %u",ans[i]);printf("\n");
    }
    return 0;
}

I:留坑

J:留坑

K:

题意:输入一个n和一个k,每天选一个可以用的最小的数,并将该数扔到一个垃圾堆里..当垃圾堆里有n-1个数时..就将这些数重新排序再放回去.问第k次你取出的是哪个数.

思路:先找规律找出循环节,再分类讨论.

贴我的代码:

#include <cstdio>
using namespace std;
int T;
long long n,m;
int main(){
    while (~scanf("%lld%lld",&n,&m)){
        printf("Case #%d: ",++T);
        if (m<=n){printf("%lld\n",m);continue;}
        long long t=(m-n)%(n-1+n-2+1);
        if (t==0)t=(n-1+n-2+1);
        if(t<=n-1)printf("%lld\n",t);
        else if (t==(n-1+n-2+1))printf("%lld\n",n);
        else printf("%lld\n",t-(n-1));
    }
    return 0;
}

l:留坑

posted @ 2017-07-27 15:26  Acheing  阅读(510)  评论(0编辑  收藏  举报