20181029(高精度(其實不用)+高精度(其實分解質因數推論)+大力打表+網絡流)

今天的模擬賽並不想做什麼總結,也不想寫題解。

進制

讀入p; q; r,求出最小的b(2 ⩽ b ⩽ 16) 使得在b 進制下pb qb = r(pb
爲p 在b 進制下的表示,比如1016 = 1610; 216 816 = 1016)。
若不存在合法的b 輸出0。
1.1 輸入格式
輸入文件爲base:in。
第一行爲數據組數T。
接下來T 行每行三個整數p; q; r,其中p; q 爲十進制數,r 是全由數字
構成的字符串。
1.2 輸出格式
輸出文件爲base:out。
對於每組數據輸出答案。
數據保證有解。
1.3 數據範圍
令b 爲最終答案,t 爲b 進制下r 的大小。
對於所有數據,0 ⩽ p; q; t ⩽ 1018; 1 ⩽ T ⩽ 104。
對於60% 的數據,p; q; t ⩽ 109。

置換

對於給定的長度爲n 的置換p,求最小的k 使得[1; 2 : : : n]pk = [1; 2 : : : n]。
定義置換a b = c 爲,cbi = ai(1 ⩽ i ⩽ n),其中a; b; c 均爲長度爲n
的置換。
由於k 可能很大,請輸出k mod 19184192。
2.1 輸入格式
輸入文件爲perm:in。
第一行一個整數n。
第二行n 個整數表示p。
2.2 輸出格式
輸出文件爲perm:out。
僅一行輸出答案。
2.3 數據範圍
對於所有數據,n ⩽ 105。
對於40% 的數據,n ⩽ 100。
對於60% 的數據,k ⩽ 1018。

24 點

24 點是一個大家熟知的遊戲。
請求解由n 個n 組成的24 點遊戲。
3.1 輸入格式
輸入文件爲card:in。
第一行爲數據組數T。
接下來T 行,每行一個整數表示n。
3.2 輸出格式
輸出文件爲card:out。
對於每組數據,輸出n 􀀀 1 行:
若無解輸出􀀀1。
否則,令A 爲長度2n 􀀀 1 的數組,初始時81 ⩽ i ⩽ n;Ai = n,表示
初始的n 個n。
對於你輸出的第i 行,格式爲a op b(1 ⩽ a; b < n + i),其中op 爲操
作類型(加+ 減􀀀 乘 實數除/),該操作將Aa op Ab 賦值給An+i。
你的輸出需要保證:
• A2n􀀀1 = 24
• 每一個Ai 只被至多使用了一次
• A 中任意元素的分子分母的絕對值不大於109。
3.3 數據範圍
對於所有數據
Σ
n ⩽ 105; n ⩽ 200。
對於30% 的數據n ⩽ 6。
對於50% 的數據n ⩽ 15。
對於70% 的數據n ⩽ 30。

反思一下吧:
1.代碼能力還是不夠強。
第一題的高精度勉勉強強過了樣例,滿心以爲是對的,結果爆0,還不停地爆0,怎麼測怎麼錯,說實話到現在也沒發現哪裏錯了。。。。(最近這種情況好多,打完了自信過樣例,隨便做了幾組小數據過了就好了,老是有一點小錯誤)
2.T2也是高精度,(雖然正解是分解質因數來推結論,但是高精度很直白)。。。於是調了巨久也沒有調對,對於高精度取模操作,怎麼調也不對,
3.T3來不及了,題解應該是24以前手推,24以後推規律
4.T4的話,時間上有一點來不及。。最後發現自己求錯東西了,求的是等待時間,我做成求通過時間加上等待時間了,然後因爲本身是求總時間,所以就怎麼也過不去。。。。(等我研究一下再)

題解:
T1:題目中肉眼可見。
題意沒有說清楚,所以明顯的高精度比較穩妥。
下面給出我的代碼和題解代碼,求查錯
我滴垃圾代碼

#include<bits/stdc++.h>
using namespace std;
long long n,m,r;
long long a[110],b[110],c[110],d[220],lenr;
bool zhuan(long long x,long long y,int chu)
{
        memset(a,0,sizeof(a));
        memset(b,0,sizeof(b));
        memset(d,0,sizeof(d));
        int lena=0;
        while (x)
         {
            a[++lena]=x%chu;
            x/=chu;
         }
        int lenb=0;
        while (y)
         {
            b[++lenb]=y%chu;
            y/=chu;
         }
        for (int i=1; i<=lena; i++)
          for (int j=1; j<=lenb; j++)
              d[i+j-1]+=a[i]*b[j];
        int lend=lena+lenb-1;
        long long tmp=0;
        for(int i=1;i<=lend;i++) tmp+=d[i],d[i]=tmp%chu,tmp/=chu;
        while(tmp) d[++lend]=tmp%chu,tmp/=chu;
        if(lend!=lenr) return false;
        for (int i=1; i<=lend; i++)
            if (d[i]!=c[i]) return false;
        return true; 
}

int main()
{
    int T;
    cin>>T;
    while (T--)
      {
        memset(c,0,sizeof(c));
        scanf("%lld%lld%lld",&n,&m,&r);
        cout<<n<<" "<<m<<" "<<r<<"\n";return 0;
        if((n==0||m==0)&&r==0){
            printf("2\n");
            continue;
        }
        lenr=0;
        while (r)
         {
           c[++lenr]=r%10;
           r/=10;
         }
        bool p=false;
        for (int op=2; op<=16; op++)
         { 
            p=zhuan(n,m,op); 
            if (p) {printf("%d\n",op);break;}
         }
        if(!p) printf("0\n");
        cout<<p<<"\n";
      }
}

跟我一樣方法的ak代碼

#include<bits/stdc++.h>
#define ll long long
using namespace std;
struct lll{
    int len,p[110];
    void read(){
        string s;cin>>s;len=s.size();
        for(int i=0;i<len;i++) p[len-i]=s[i]-'0';
    }
    bool operator == (const lll x) const{
        if(len!=x.len) return false;
        for(int i=1;i<=len;i++) if(p[i]!=x.p[i]) return false;
        return true;
    }
    void turn_it(int bas,ll t){
        len=0;
        while(t) p[++len]=t%bas,t/=bas;
    }
    void out(){
        for(int i=len;i>=1;i--){
            if(p[i]<10) cout<<p[i];
            else cout<<p[i]-10+'A';
        }
        cout<<"\n";
    }
}p,q,r,base0;
int base;
ll a,b,T;

lll multy(lll x,lll y){
    lll z=base0;
    for(int i=1;i<=x.len;i++)
        for(int j=1;j<=y.len;j++)
            z.p[i+j-1]+=x.p[i]*y.p[j];
    z.len=x.len+y.len-1;
    long long tmp=0;
    for(int i=1;i<=z.len;i++) tmp+=z.p[i],z.p[i]=tmp%base,tmp/=base;
    while(tmp) z.p[++z.len]=tmp%base,tmp/=base;
    return z;
}

int main(){
    base0.len=1;
//  freopen("base.in","r",stdin);
//  freopen("base.out","w",stdout);
    scanf("%lld",&T);
    while(T--){
        bool flag=false;
        scanf("%lld%lld",&a,&b);r.read();
        if(r==base0&&(a==0||b==0)){
            puts("2");
            continue;
        }
        for(int i=2;i<=16;i++){
            base=i,p.turn_it(i,a),q.turn_it(i,b);
            if(r==multy(p,q)){
                flag=true,printf("%d\n",i);
                break;
            }
        }
        if(!flag) puts("0");
    }
}

T2
題意概括:就是 1n1-n(a數組)和p這個數組進行k次題目中說的乘法操作得到c數組(c[p[i]]=a[i]c[p[i]]=a[i]),多少次重新回到1n1-n

打表出規律
高精就ak

#include<iostream>
#include<cstdio>
#include<memory.h>
using namespace std;
#define MOD 19184192
struct gaojingdu
{
    int a[10005],len;
    gaojingdu()
    {
        memset(a,0,sizeof(a));
        len=0;
    }
    gaojingdu operator +(gaojingdu x) const
    {
        gaojingdu y;
        y.len=max(x.len,len);
        for (int i=1;i<=y.len;i++)
        {
            y.a[i]+=a[i]+x.a[i];
            y.a[i+1]+=y.a[i]/10;
            y.a[i]%=10;
        }
        if (y.a[y.len+1]!=0) y.len++;
        return y;
    }
    gaojingdu operator *(gaojingdu x) const
    {
        gaojingdu t;
        t.len=x.len+len-1;
        for (int i=1;i<=x.len;i++)
        {
            for (int j=1;j<=len;j++)
            {
                t.a[i+j-1]+=x.a[i]*a[j];
                t.a[i+j]+=t.a[i+j-1]/10;
                t.a[i+j-1]%=10;
            }
        }
        while (t.a[t.len+1]>0)
        {
            t.len++;
            t.a[t.len+1]=t.a[t.len]/10;
            t.a[t.len]%=10;
        }
        return t;
    }
    gaojingdu operator /(long long x) const
    {
        gaojingdu t;
        t.len=len;
        long long y=0;
        for (int i=len;i>=1;i--)
        {
            y=y*10+a[i];
            t.a[i]=y/x;
            y%=x;
        }
        while (t.a[t.len]==0) t.len--;
        return t;
    }
    long long operator %(long long x) const
    {
        gaojingdu t;
        t.len=len;
        long long y=0;
        for (int i=len;i>=1;i--)
        {
            y=y*10+a[i];
            t.a[i]=y/x;
            y%=x;
        }
        return y;
    }
    bool operator ==(gaojingdu x)
    {
        if (x.len!=len) return false;
        for (int i=1;i<=len;i++)
        {
            if (a[i]!=x.a[i]) return false;
        }
        return true;
    }
};
long long pow(long long x,int y)
{
    long long t=1;
    while (y>0)
    {
        if (y%2==1) t=t*x;
        x*=x;
        y/=2;
    }
    return t;
}
gaojingdu zhuan(string s)
{
    gaojingdu x;
    x.len=s.size();
    for (int i=1;i<=x.len;i++)
    {
        x.a[i]=s[x.len-i]-'0';
    }
    return x;
}
gaojingdu zhuan(long long x)
{
    gaojingdu z;
    z.len=0;
    while (x>0)
    {
        z.len++;
        z.a[z.len]=x%10;
        x/=10;
    }
    return z;
}
long long zhuan(gaojingdu x)
{
    long long y=0;
    for (int i=x.len;i>=1;i--)
    {
        y=y*10+x.a[i];
    }
    return y;
}
gaojingdu zhuan(long long x,int y)
{
    gaojingdu z;
    while (x>0)
    {
        z.len++;
        z.a[z.len]=x%y;
        x/=y;
    }
    return z;
}
void write(gaojingdu x)
{
    for (int i=x.len;i>=1;i--)
    cout<<x.a[i];
}
int n,a[100005],b[100005];
long long gcd(gaojingdu x,long long y)
{
    return y==0?zhuan(x):gcd(zhuan(y),x%y);
}
gaojingdu lcm(gaojingdu x,long long y)
{
    return x/gcd(x,y)*zhuan(y);
}
int main()
{
//  freopen("perm.in","r",stdin);
//  freopen("perm.out","w",stdout);
    cin>>n;
    for (int i=1;i<=n;i++) scanf("%d",&a[i]);
    gaojingdu ans=zhuan(1);
    for (int i=1;i<=n;i++)
    {
        if (b[i]==1) continue;
        int j=a[i];
        long long x=1;
        while (j!=i)
        {
            b[j]=1;
            j=a[j];
            x=x+1;
        }
        ans=lcm(ans,x);
    }
    cout<<ans%MOD;
}

T3
題意概括:大家應該都玩過24點?求n個n能否構成24點。

來不及,就手動推了前五組。。
懶得寫題解了。。。。見代碼。。。

# include <bits/stdc++.h> 
using namespace std;  
int main()  
{  
//    freopen("card.in","r",stdin);
//    freopen("card.out","w",stdout);
    int n,tmp, T; 
    scanf ("%d", &T);
    for (int t = 1; t <= T; ++ t){  
        scanf ("%d", &n);
        switch (n) {
            case 1:printf("-1\n");break;
            case 2:printf("-1\n");break;
            case 3:printf("-1\n");break;
            case 4:printf("1 * 2\n5 + 3\n6 + 4\n");  break;
            case 5:printf("1 * 2\n3 / 6\n4 - 7\n5 * 8\n"); break;
            case 6:printf("1 + 2\n3 + 4\n5 - 6\n7 + 8\n10 - 9\n");  break;
            case 7:printf("1 + 2\n3 + 8\n9 / 4\n10 + 5\n11 + 6\n12 + 7\n"); break;
            case 8:printf("1 + 2\n3 + 9\n4 - 5\n11 * 6\n12 * 7\n13 * 8\n10 + 14\n");break;
            case 9:printf("1 + 2\n3 + 10\n4 / 5\n6 / 7\n8 / 9\n11 - 12\n15 - 13\n 16 - 14\n");  break;
            case 10:printf("1 + 2\n3 / 4\n5 / 6\n7 / 8\n9 / 10\n11 + 12\n16 + 13\n17 + 14\n18 + 15\n");break;
            case 11:printf("1 + 2\n3 / 4\n5 / 6\n7 - 8\n15 * 9\n16 * 10\n17 * 11\n12 + 13\n19 + 14\n20 + 18\n");  break;
            case 12:printf("1 + 2\n3 - 4\n5 * 14\n6 * 15\n7 * 16\n8 * 17\n9 * 18\n10 * 19\n11 * 20\n12 * 21\n13 + 22\n");  break;
            case 13:printf("1 + 2\n3 / 4\n5 / 6\n7 - 8\n17 * 9\n18 * 10\n19 * 11\n20 * 12\n21 * 13\n22 + 14\n23 - 15\n24 - 16\n"); break;
            default: {
                printf("1 + 2\n3 + 4\n5 + 6\n7 + 8\n9 + 10\n");  
                printf("%d + %d\n%d + %d\n%d + %d\n",n+1,n+2,n+3,n+4,n+5,n+6);  
                printf("%d / 11\n%d / 12\n",n+7,n+8);  
                printf("%d * %d\n",n+9,n+10);  
                printf("13 - 14\n");  
                tmp=n-14;  
                int i;  
                for(i=0;i<tmp;i++) printf("%d * %d\n",n+12+i,15+i);  
                printf("%d + %d\n",n+11,n+12+tmp);  
              }  
                break;
            }
    }  
    return 0;  
}

T4
3.飛揚的小鳥
(bird.cpp\c\pas)
【問題描述】
Flappy Bird是一款風靡一時的休閒手機遊戲。玩家需要不斷控制點擊手機屏幕的頻率來調節小鳥的飛行高度,讓小鳥順利通過畫面右方的管道縫隙。如果小鳥一不小心撞到了水管或者掉在地上的話,便宣告失敗。
現在小鳥們遇到了一個難題,他們遇到了一堵巨大的牆,牆上僅有m個洞供他們通過,由於小鳥們的體型不同且牆上洞的形狀也不同,所以每種體型的鳥通過每個洞的時間都不同,鳥的體型共有n種,第i種體型的鳥通過第j個洞需要的時間記爲T(i,j),且一個洞必須前一隻鳥通過之後後一隻鳥才能開始通過。
從時刻0開始,鳥開始通過,而每一隻鳥的等待時間爲從時刻0到自己已經通過洞的時間。現在知道了第i種體型的鳥有pi只,請求出使所有鳥都通過牆的最少的等待時間之和。
【輸入格式】
第1行包含兩個正整數n和m,表示鳥的體型的種數和牆洞的數量。
第2行包含n個正整數,其中第i個數爲pi,表示點第i種體型的鳥的只數。
接下來有n行,每行包含m個非負整數,這n行中的第i行的第j個數爲t(i,j),表示第i種體型的鳥通過第j個牆洞所需的時間。輸入文件中每行相鄰的兩個數之間均由一個空格隔開,行末均沒有多餘空格。
【輸出格式】
輸出僅一行包含一個整數,爲總等待時間的最小值。

題意概括:
n種鳥,m個洞,不同種鳥過不同種洞有不同時間,求最少等待時間(後面等待的鳥等待的時間)。

這個題是今天最有含金量的題了,可惜沒題解??
乍一眼看可能個排隊接水的進階版很像,可惜肯定不是貪心,DP的話額、
DP個屁啊,
尼瑪我@#¥%&YUI&%$#$%U

網絡流

考慮如果一隻種類爲i的鳥倒數第一個通過洞j,那麼對於總代價的貢獻爲T(i,j),倒數第k則貢獻爲T(i,j)*k。
根據這個,我們就可以建圖了。
源點向每一種鳥連邊,對於第i種鳥,連一條流量爲p[i]費用爲0的邊。
對於每一個洞,我們拆成p∑p個洞,也就是總共拆成了mpm*∑p的洞,每個洞向匯點連一條流量爲1費用爲0的邊。
然後每一種鳥向每一個洞都連一條邊。第i種鳥,向第(k-1)*m+j個洞(這裏指的是拆後的洞)連一條流量爲1,費用爲T(i,j)kT(i,j)*k
邊,這條邊若滿流則表示的意義爲一隻種類爲i的鳥倒數第k個通過了洞,且該洞爲第j個洞(這裏指原來的洞)。

然而點數最大爲40+100800,邊數最大爲40+10080+4010080,直接做顯然會超時。

注意到若第(k-1)m+j個洞向匯點的邊沒有滿流,則第km+j個洞顯然也不會滿流(即還用不到),以可以動態加邊。

#include<bits/stdc++.h>
#define	INF	0x3f3f3f3f
#define	LL	long long
#define	MAXD	100010
#define	MAXN	50
#define	MAXM	110
using namespace std;
int n, m, p[MAXN], t[MAXN][MAXM], cnt;
int S, T, dis[MAXD], frm[MAXD], rk[MAXD], ansflow, anscost;
struct info{int v, c, w; unsigned r;};
vector <info> a[MAXD];

template <typename T> void chkmin(T &x, T y){x = min(x, y);}
template <typename T> void chkmax(T &x, T y){x = max(x, y);}
template <typename T> void read(T &x){
	x = 0; int f = 1; char ch = getchar();
	while (!isdigit(ch)) {if (ch == '-') f = -1; ch = getchar();}
	while (isdigit(ch)) {x = x * 10 + ch - '0'; ch = getchar();}
	x *= f;
}

void add(int u, int v, int c, int w){
	a[u].push_back((info){v, c, w, (unsigned)a[v].size()});
	a[v].push_back((info){u, 0, -w, (unsigned)a[u].size() - 1});
}

int spfa(){
	static int q[MAXD * 200], inq[MAXD], l = 0, r = 0;
	for (int i = 0; i <= r; ++i)
		dis[q[i]] = INF;
	q[l = r = 0] = S, dis[S] = 0, inq[S] = 1;
	while (l <= r) {
		int pos = q[l++];
		for (unsigned i = 0, si = a[pos].size(); i < si; ++i){
			int to = a[pos][i].v, wth = a[pos][i].w, cap = a[pos][i].c;
			if (cap && dis[to] > dis[pos] + wth) {
				dis[to] = dis[pos] + wth;
				frm[to] = pos, rk[to] = i;
				if (!inq[to]) q[++r] = to, inq[to] = 1;
			}
		}
		inq[pos] = 0;
	}
	return (dis[T] != INF);
}

void flow(){
	int pos = T, f = INF;
	while (pos != S) {
		info tmp = a[frm[pos]][rk[pos]];
		chkmin(f, tmp.c);
		pos = frm[pos];
	}
	ansflow += f, anscost += f * dis[T], pos = T;
	while (pos != S) {
		info &tmp = a[frm[pos]][rk[pos]];
		tmp.c -= f;
		a[pos][tmp.r].c += f;
		pos = frm[pos];
	}
}

void addedg(int dep){
	for (int i = 1; i <= m; ++i){
		int d = ++cnt;
		add(d, T, 1, 0);
		for (int j = 1; j <= n; ++j)
			add(j, d, 1, dep * t[j][i]);
	}
}

int main(){
	freopen("bird.in", "r", stdin);
	freopen("bird.out", "w", stdout);
	memset(dis, INF, sizeof(dis));
	read(n), read(m);
	for (int i = 1; i <= n; ++i)
		read(p[i]);
	for (int i = 1; i <= n; ++i)
		for (int j = 1; j <= m; ++j)
			read(t[i][j]);
	S = 0, T = n + 1, cnt = n + 1;
	for (int i = 1; i <= n; ++i)
		add(S, i, p[i], 0);
	int dep = 1;
	addedg(dep);
	while (spfa()){
		flow();
		++dep;
		addedg(dep);
	} 
	printf("%d\n", anscost);
	return 0;
}

今天估分 100+50(高精度寫掛了,交了暴力,不知道爲啥暴力也掛了)+10+0
實際:

0

憑實力爆的0,絕對沒有結果,就是代碼能力不夠,沒有什麼其他原因,如何證明這不是自己的實力?那就是明天好好打,該拿的分絕對不能放。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章