CXMS 瞎几把胡策题 ROUDN1

T1 :

修复道路 (path.cpp)

时限:2s    内存:128MB

题目描述

    夜深了,xcy正做着美梦((~﹃~)~zZ)……

    20年后,xcy成为了伟大的设计建筑家。他所在的城市有N个区域,这些区域是通过M条道路连接的(然而这些道路都已损坏),每条道路都有一定的长度。市长希望他将一些道路修复(各个区域可能并不连通),使得任意一个区域能互相连通。此外市长还希望有且仅有K个区域与市政府(节点1)连通,并且使得路径和最小。

    xcy一脸懵逼,便来求助于你了

输入格式

    第一行三个整数N,M,K。其中N为城市的区域数,M为道路数量,K为与市政府连通的道路数(可能有重边)。

    第2至M+1行每行两个整数ui,vi和一个实数wi,表示ui与vi之间有一条长度为wi的道路。

输出格式

    共一行,两个整数,表示最小路径和。

    若不存在这样的情况,输出-1。

输入样例1

4 5 2

1 2 1

2 3 1

3 4 1

1 3 3

1 4 2

输出样例1

4

样例说明1

    选1、25(或1、35)三条边。

输入样例2

8 10 2

1 2 1

1 3 2

1 4 3

1 5 4

2 6 5

6 7 2

3 7 3

4 7 3

3 8 3

5 8 1

输出样例2

15

数据规模

100%的数据: 1 ≤ n ≤ 5000; 0 ≤ m ≤ 100000; 0 ≤ k < 5000;

1 ≤ ui, vi ≤ n;; 1 ≤ wi ≤ 100000
题目

SOL: 本来想着把1弄走后跑树上背包的,脑子一抽没写出来(也不知道对不对。虽然不保证生成树唯一,但拟阵有很多优秀的性质,说不定是对的,反正学弟出的题,也不会卡这个对不对)。 然后STD是wqs 二分。

  (⊙o⊙)… 后生可畏。

#include<bits/stdc++.h>
#define eho(x) for(int i=head[x];i;i=net[i])
#define N 400007
#define sight(c) ('0'<=c&&c<='9')
#define v fall[i]
#define exp 1e-6
#define inf (1<<28)
#define db double
using namespace std;
#define M 8007
int fp[M],f[N],fall[N],net[N],cost[N],head[M],tot,usd[N];
int n,m,k,x,y,w,fx,fy,Tot;
struct Node{
    int id,x,cc,ud;
    inline bool operator <(const Node&X)const{
       return x==X.x?cc>X.cc:x<X.x;
    }
}p[N];
struct Eg{
    db w; int x,y;
    inline bool operator <(const Eg&X)const{
       return w<X.w;
    }
}e[N];
inline void read(int &x){
    static char c;
    for (c=getchar();!sight(c);c=getchar());
    for (x=0;sight(c);c=getchar())x=x*10+c-48;
}
void write(int x){if (x<10) {putchar('0'+x); return;} write(x/10); putchar('0'+x%10);}
inline void writeln(int x){ if (x<0) putchar('-'),x*=-1; write(x); putchar('\n'); }
inline void writel(int x){ if (x<0) putchar('-'),x*=-1; write(x); putchar(' '); }
int getfa(int x){
    return f[x]==x?x:f[x]=getfa(f[x]);
}
int rr;
db anw;
bool check(db x) {
    rr=0; anw=0;
    for (int i=1;i<=n;i++) f[i]=i;
    for (int i=1;i<=Tot;i++) if (e[i].x==1) e[i].w+=x;
    sort(e+1,e+Tot+1);
    for (int i=1;i<=Tot;i++) {
        fx=getfa(e[i].x); fy=getfa(e[i].y);
        if (fx==fy) continue;
        f[fx]=fy;
        anw+=e[i].w;
        if (e[i].x==1) rr++;
    }
    for (int i=1;i<=Tot;i++) if(e[i].x==1) e[i].w-=x;
    return rr<=k;
}
int der;
#define Mid ((L+R)*0.5)
signed main() {
    freopen("path.in","r",stdin);
    freopen("path.out","w",stdout);
//    read(n); read(m); read(k);
    scanf("%d%d%d",&n,&m,&k);
    for (int i=1;i<=n;i++) f[i]=i,p[i].id=i,p[i].x=inf;
    for (int i=1;i<=m;i++) {
        scanf("%d%d%d",&x,&y,&w);
        if (x>y) swap(x,y);
        e[++Tot].x=x,e[Tot].y=y,e[Tot].w=w;
        if (e[Tot].x==1) der++;
    }
    cerr<<der<<' '<<k<<endl;
    
    if ((k==0&&n>1)||der<k||(m<n-1)) {writeln(-1); return 0;}
    check(0);
    int ft=getfa(1);
    for (int i=2;i<=n;i++) if (ft^getfa(i)) {
        writeln(-1); return 0;
    }
    db L,R;
    L=-1000000; R=1000000;
    while (R-L>exp)  
     if (check(Mid)) R=Mid; else L=Mid; 
    check(R);
    if (Mid<-100000||Mid>100000) {
        writeln(-1); return 0;
    }
    cerr<<k<<"  "<<rr<<endl;
    writeln(anw-k*L+10*exp);
    return 0;
}
My code

 T2  :

小朋友的难题   question.cpp
                        时限:2 Sec       内存:512MB
题目描述
    上周,xcy参加了全国小学生综合素养竞赛。令他始料未及的是,他得了倒数第二名。面对小朋友们的嘲笑,他来向你求助,希望你能帮他解决考试中最难的一题。
    题目是这样的:给你N个长度相同的字符串(由小写字母和’?’组成),s1,s2…,sn。求与这N个串中刚好K个串匹配的字符串T的个数(答案模1000003)。
    若字符串sx(1<=x<=N) 和T匹配,满足以下条件:
1.    Sx.length=T.length.
2.    对于任意1<=i<=sx.length,满足sx[i]=’?’或sx[i]=T[i],其中T只包含小写字母。
输入格式
本题包含多组数据。 第一行:一个整数T,表示数据的个数。 对于每组数据: 第一行:两个整数,N和K(含义如题目表述)。 接下来N行:每行一个字符串。
输出格式
如题
输入输出样例
question.in
5
3 3
???r???
???????
???????
3 4
???????
?????a?
???????
3 3
???????
?a??j??
????aa?
3 2
a??????
???????
???????
3 2
???????
???a???
????a??

question.out
914852
0
0
871234
67018
说明
对于30%的数据,T ≤ 3,M ≤ 5,字符串长度≤ 20;
对于70%的数据,T ≤ 3,M ≤ 16,字符串长度≤ 30;
对于100%的数据,T ≤ 3,M ≤ 21,字符串长度≤ 50
题目

SOL: 不知道为什么,这道题长得像暴力能过的样子,然后就过了。类似容斥一样的东西,那个转移系数自己算一下就好了。

我甚至没卡常,可能是数据友好吧。

#pragma GCC optimize("-Ofast")
#include<bits/stdc++.h>
#define mo 1000003
using namespace std;
char ch[23][53],cp;
int anw,p,n,m,a[23],T,len,op;
long long ans,c[23][23],opp[23];
void work() {
    anw=1;
    for (int i=1;i<=len;i++) {
     p=26;
     for (int j=1;j<=op;j++)
      if (ch[a[j]][i]!='?') {
          if (p==26) p=1,cp=ch[a[j]][i];
          else if (p==1&&cp!=ch[a[j]][i]) return;
      }
      anw=anw*p%mo;
    }
    ans+=opp[op]*anw%mo;
}
void dfs(int x){
    if (x==n+1) {
        if (op<m) return;
        work(); return;
    }
    a[++op]=x;
    dfs(x+1);
    op--;
    dfs(x+1);
}

signed main () {
    freopen("question.in","r",stdin);
    freopen("question.out","w",stdout);
    for (int i=1;i<=22;i++) {
     c[i][0]=c[i][i]=1;
     for (int j=1;j<i;j++)
      c[i][j]=(c[i-1][j-1]+c[i-1][j])%mo;
    }
//    for (int i=1;i<=)
    scanf("%d",&T);
    while (T--) {
        memset(opp,0,sizeof opp);
        scanf("%d%d",&n,&m);
        ans=0;
        for (int i=1;i<=n;i++) scanf("%s",ch[i]+1);
        len=strlen(ch[1]+1);
        opp[m]=1;
        for (int i=m+1;i<=n;i++) {
          for (int j=m;j<i;j++)
           opp[i]-=c[i][j]*opp[j]%mo; 
          opp[i]=opp[i]%mo;
        }
        dfs(1);
        printf("%lld\n",(ans%mo+mo)%mo);
    } return 0;
}
My code

 T3  :

买彩票(lottery.cpp)
时限:1s  内存:512MB
题目背景 
婷婷是一个热衷于买彩票的女孩子。 
题目描述 
今天,婷婷又去买彩票了。彩票号码的长度为n,所有由0-9的数字组成的n位号码都可以购买,但只有一张是中奖号码。根据她以往的经验,她可以确定所有含有长度为m的不吉利序列的彩票号码是不可能中奖的。
但即使这样,她的中奖概率仍然很低。于是她找来了cqh。cqh可以使用念力。当可能的彩票数量大于k时,他可以排除k张不会中奖的彩票。这个操作可以经行多次,直到剩余的可能的彩票数量小于等于k。
婷婷每次只会买一张彩票,现在她想知道她中奖的概率有多少,我们认为每张未被确认为不可能中奖的彩票中奖概率相等,这次只有一张彩票会中奖。并且每张彩票只有中奖与不中奖这两种可能。 
输入格式 
第一行有四个数n,m,k,l。l表示婷婷希望概率能精确到小数点后l位 
第二行是一个m位的数字序列,表示不吉利序列
输出格式 
婷婷中奖的概率 
输入样例
4 3 100 23 
111 
输出样例 
0.01234567901234567901235 
数据范围 
30%数据N<=1000 
90%数据N<=1000000 
100%的数据N<=10^10,M<=20,K<=10000,L<=10000; 
题目

SOL :就是一个很简单的DP呢,也没有特征向量优化矩阵幂。还写残了,只能感叹自己老了。

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

#define oo 0x3f3f3f3f
#define mp make_pair
#define fi first
#define se second
#define debug(...) fprintf(stderr, __VA_ARGS__), fflush(stderr)
#define FO(i,a,b) for (int i=(a);i<=(b);++i)
#define FD(i,a,b) for (int i=(a);i>=(b);--i)
#define LL long long

template <class T> inline bool chkmin(T& x, T y) { return x > y ? x = y, true : false; }
template <class T> inline bool chkmax(T& x, T y) { return x < y ? x = y, true : false; }

inline LL read(void) {
    LL x, f = 1; char ch = getchar();
    for (; !isdigit(ch); ch = getchar()) if (ch == '-') f = -1;
    for (x = 0; isdigit(ch); ch = getchar()) x = x * 10 + ch - '0';
    return x * f;
}

LL n;
int m,MO,l,nxt[25];
int a[10005];
char s[25];

int get(int x){
    FD(i,x-1,1){
        bool flag=1;
        FO(j,1,i) if (s[j]!=s[x-i+j]) { flag=0; break; }
        if (flag) return i;
    }
    return 0;
}
int C[21][21],M[21][21],A[21][21];
void mul(int A[21][21],int B[21][21]){
    FO(i,0,m)FO(j,0,m){
        C[i][j]=0;
        FO(z,0,m) (C[i][j]+=1ll*A[i][z]*B[z][j]%MO)%=MO;
    }
    memcpy(A,C,sizeof(C));
}
int main() {
    freopen("lottery.in","r",stdin);
    freopen("lottery.out","w",stdout);
    n=read();m=read();MO=read();l=read();
    scanf("%s",s+1);
    M[0][0]=9,M[0][1]=1;
    FO(i,1,m-1){
        FO(ch,'0','9'){
            if (ch==s[i+1]) {M[i][i+1]++;continue;}
            int rc=-1;
            FD(j,i,1){
                if (ch!=s[j]) continue;
                bool flag=1;
                FO(z,1,j-1) if (s[z]!=s[i+1-j+z]) { flag=0; break; }
                if (flag) { rc=j;break; }
            }
            if (rc==-1) M[i][0]++;
            else M[i][rc]++;
        }
    }
    memcpy(A,M,sizeof(M));n--;
    for (;n;n>>=1){
        if (n&1) mul(A,M);
        mul(M,M);
    }
    int ans=0;
    FO(i,0,m-1) (ans+=A[0][i])%=MO;
    if (ans==0){
        printf("1.");
        FO(i,1,l) putchar('0');
        puts(""); return 0;
    }
    printf("0.");
    LL y=10;
    FO(i,1,l+1){
        if (y<ans) y*=10,a[i]=0;
        else a[i]=y/ans,(y%=ans)*=10;
    }
    if (a[l+1]>=5){
        a[l]++;
        FD(i,l-1,1) a[i]+=a[i+1]/10,a[i+1]%=10;
    }
    FO(i,1,l) putchar(a[i]+48);
    return 0;
}
Not My code

 

posted @ 2018-05-09 20:57  泪寒之雪  阅读(199)  评论(0编辑  收藏  举报