CF327

A題:Flipping Game

題意:n個數字由0,1組成,一次反轉定義爲將連續的n個0翻轉爲1.求經過一次翻轉後,1的個數做多是多少???

很水的一道題,方法就是求出1的個數和連續0個數最多的區間長度。二者相加就是答案~~~

#include <iostream>
#include<stdio.h>
using namespace std;
int main()
{
	int i,n,a,x,y,mx;
	cin >> n;
	mx=0,x=0,y=0;
	for(i=0;i<n;i++)
	{
		cin >> a;
		if(a) y++;
		if(!a)
		{
		    x++;
		    if(x>mx)
		    mx=x;
		}
		else if(x>0) x--;
	}
	if(!mx) mx--;
	cout << y + mx << endl;
	return 0;
}


B題:Hungry Sequence

這道題,要求不是很嚴格~~只要輸出那個數,其中任意兩個數不能整除就可以,那麼n—2*n-1之間的連續n個數任意兩個都不能整除,輸出即可

#include <iostream>
using namespace std;
int main()
{
    int n,i;
    cin>>n;
    for(i=n; i<2*n; ++i)
        cout << i << " ";
    return 0;
}


C題:Magic Five

題意:有一個字符串,可以在這個串中去掉0個或者多個(不能全部)字符使能夠被5整除。求共有多少種方式?

輸入:一個字符串s和整數k,表示k個s相連接。

輸出:有多少種方式是字符串表示的數能夠被5整除。

解題方法:根據快速冪和費馬小定理求解。否則會TLE。

思路:設max=1000000007先求出一個字符串的長度l,在求出一個串時的方法數a1,那麼家下來k-1接上的時候會成一個等比數列,即:a1,a1*( 2 ^ l ),a1*( 2 ^ (2l)  ),…………,

a1*( 2 ^ (k-1)l )。那麼如果根據等比數列前n項和的公式求出:sum=a1 * ( 2 ^ ( k* l) -1 )/( 2 ^ l -1 )。這樣做的話會wa掉,因爲有除法,分子要對max取模,那麼就不一定能夠整除分母。下面採用費馬小定理求逆元的辦法。

設分子爲a,分母爲b。那麼sum=a1* a/b%max。設b的逆元是p,那麼b*p=1。那麼,sum=a1*a*p%max。那接下來胖怎麼求呢?

根據費馬小定理:a ^ (p-1)=1(mod p),前提是a,p互質。有題知:b和max互質,則b ^ (max-1)=1(mod max)。所以b*b^(max-2)=1;即p=b^(max-2)。

所以,sum=((a1*a)%max)*(b ^ (max-2))%max,其中a=2 ^ ( k* l) -1,b=2 ^ l -1。式子中所有的冪數都要用快速冪來求。

這道題,受益良多啊~~~快速冪更加深了印象,還學會了費馬小定理~~~。

code:

#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <string>
#include <cmath>
using namespace std;
#define MAX 1000000007
__int64 mode(__int64 a, __int64 n)
{
    __int64 t = a;
    __int64 ans = 1;
    while(n)
    {
        if(n & 1)
        {
            ans = ans * t%MAX;
        }
        n >>= 1;
        t =  t * t%MAX;
    }
    return ans;
}
int main()
{
    __int64 k,t1,t2;
    string s;
    cin >> s >> k;
    __int64 i,ans=0,sum=1;
    __int64 l1=s.length();
    for(i=l1-1; i>=0; i--)
    {
        if(s[i]=='0'||s[i]=='5')
            ans=(ans+mode(2,i))%MAX;
    }
    ans=((ans*(mode(2,l1*k)-1))%MAX)*mode(mode(2,l1)-1,MAX-2)%MAX;
    cout << ans%MAX << endl;
    return 0;
}

D題:Block Tower

題意:
.代表空地,#代表洞,空地可以建塔。塔分爲兩種:藍色的塔,可以建在空地上。紅色的塔,必須周圍有藍色的纔可以建。還可以將藍色的拆掉在建紅色的。求建成紅色塔最多的過程~~~,注意Note, that you shouldn't minimize the number of operations這句話,說明答案不是唯一的~~~

思路:dfs搜素就可以了,

code:

#include <iostream>
#include <stdio.h>
#include <string>
#include <algorithm>
using namespace std;
char map[550][550];
int vis[550][550]={{0}};
char c[100000005];
int x[100000005];
int y[100000005];
int m,n;
int sum=0;
void dfs(int a,int b,int t)
{
    if(a<1||a>n||b<1||b>m)return ;
    c[sum]='B';
    x[sum]=a;
    y[sum]=b;
    sum++;
    vis[a][b]=0;
    if(vis[a-1][b])
        dfs(a-1,b,1);
    if(vis[a+1][b])
        dfs(a+1,b,1);
    if(vis[a][b-1])
        dfs(a,b-1,1);
    if(vis[a][b+1])
        dfs(a,b+1,1);
    if(t)
    {
        c[sum]='D';
        x[sum]=a;
        y[sum]=b;
        sum++;
        c[sum]='R';
        x[sum]=a;
        y[sum]=b;
        sum++;
    }
}
int main()
{
    int i,j;
    cin >> n >> m;
    for(i=1; i<=n; i++)
        for(j=1; j<=m; j++)
        {
            cin >> map[i][j];
            if(map[i][j]=='.')
                vis[i][j]=1;
        }
    for(i=1; i<=n; i++)
        for(j=1; j<=m; j++)
        {
            if(vis[i][j])
                dfs(i,j,0);
        }
    cout << sum << endl;
    for(i=0; i<sum; i++)
    {
        cout << c[i] << " " << x[i] << " " << y[i] << endl;
    }
    return 0;
}


E題:Axis Walking

題意:有n個數,那麼由這n個數到達這些數的總和,但是不能到達給出的指定的數。求出共有多少種方式到達?

思路:狀態壓縮DP,還沒有懂,先轉過來~~~~

01.#include <iostream>  
02.#include <cstdio>  
03.#include <algorithm>  
04.#include <string>  
05.#include <cmath>  
06.#include <cstring>  
07.#include <queue>  
08.#include <set>  
09.#include <vector>  
10.#include <stack>  
11.#include <map>  
12.#include <iomanip>  
13.#define PI acos(-1.0)  
14.#define Max 2505  
15.#define inf 1<<28  
16.#define LL(x) ( x << 1 )  
17.#define RR(x) ( x << 1 | 1 )  
18.#define REP(i,s,t) for( int i = ( s ) ; i <= ( t ) ; ++ i )  
19.#define ll long long  
20.#define mem(a,b) memset(a,b,sizeof(a))  
21.#define mp(a,b) make_pair(a,b)  
22.#define PII pair<int,int>  
23.using namespace std;  
24.  
25.#define MOD 1000000007  
26.  
27.inline void RD(int &ret) {  
28.    char c;  
29.    do {  
30.        c = getchar();  
31.    } while(c < '0' || c > '9') ;  
32.    ret = c - '0';  
33.    while((c=getchar()) >= '0' && c <= '9')  
34.        ret = ret * 10 + ( c - '0' );  
35.}  
36.  
37.int a[111111] ;  
38.int sum[1 << 24] ;  
39.int dp[1 << 24] ;  
40.int k[11] ;  
41.  
42.int main(){  
43.  
44.    int n ;  
45.    cin >> n  ;  
46.    for (int i = 0 ;i < n ; i ++ ){  
47.        RD(a[i]) ;  
48.    }  
49.  
50.    int m ;  
51.    cin >> m ;  
52.    for (int i = 0 ;i < m ;i ++ ){  
53.        RD(k[i]) ;  
54.    }  
55.    dp[0] = 1 ;  
56.    for (int i = 1 ;i < (1 << n) ; ++ i){//枚舉當前路徑  
57.        int pos ;  
58.        bool flag = 0 ;  
59.        sum[i] = 0 ;  
60.        for (int j = 0 ;j < n ;j ++ ){  
61.            if(i & (1 << j)){//i 在 j 這點爲1 ,直接在這裏找出sum[i]的值會T。O(2 ^ 24 *  n)  
62.                pos = j ;//一開始我直接寫sum[i] += a[j] ;就T了  
63.                break ;  
64.            }  
65.        }  
66.        sum[i] = sum[i ^ (1 << pos)] + a[pos] ;//i 狀態的所有步數。  
67.        for (int j = 0 ; j < m ;j ++ ){//i狀態的步數是否不能走。  
68.            if(sum[i] == k[j]){  
69.                dp[i] = 0 ;  
70.                flag = 1 ;  
71.                break ;  
72.            }  
73.        }  
74.        if(flag)continue ;  
75.        dp[i] = 0 ;  
76.        for (int j = 0 ;j < n ;j ++ ){  
77.            if(i & (1 << j)){//i 這位可以由i ^ (1 << j )這一狀態過來。  
78.                dp[i] = (dp[i] + dp[i ^ (1 << j)]) ;  
79.                if(dp[i] >= MOD)dp[i] -= MOD ;  
80.            }  
81.        }  
82.    }  
83.  
84.    cout << dp[(1 << n) - 1] << endl;  
85.    return 0 ;  
86.} 


 

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