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.} 


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值