!HDU 4346 插旗子RGR的插法有多少种-思维&正难则逆&思维!

题意:只有R和G两种旗子,美丽的插法是存在两个R的中点插G的情况,现在给你一个字符串代表现在有些地方已经插了,求美丽的插法有多少种

分析:

美丽=总 — 不美丽

所以我们来求不美丽有多少种。

这里就是思维的问题了:一个不美丽的序列必须满足的条件是任何两个相邻R的距离为奇数并且所有的相邻R的距离相等。

奇数这是显然的,如果两个相邻的R不为奇数,那么它们的中点存在,并且是G,这与不美丽矛盾;

距离相等也很好证:设三个相邻的R,R1R2的距离为x1,R2R3的距离为x2,则R1R3=x1+x2,因为x1,x2都为奇数,所以他们的和为偶数,那么R1R3的中点存在,如果x1!=x2,那么就是说R1R3之间唯一的R不在他们的中点,则填充他们中点的一定是G,这与不美丽矛盾。综上即证。

接下来就是枚举!枚举R的起点和距离。注意枚举的过程,特殊情况要讨论。

代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<string>
using namespace std;
const long long INF=1000000007;
int t;
char a[1000];
int main()
{
	scanf("%d",&t);
	while(t--){
	        cin>>a;
		int len=strlen(a);
		int rall=0,num=0;
		for(int i=0;i<len;i++){
			if(a[i]=='R') rall++;
			if(a[i]=='?') num++;
		}
		long long ans=0;
		if(rall==0) ans=1; //特殊情况1,全为G
		int ok=1;
		for(int i=0;i<len;i++){
			if(a[i]=='R') ok=0;
			if(a[i]!='G'){
			    if(rall==0) ans=(ans+1)%INF; //特殊情况2,只有一个R
				if(rall==1&&a[i]=='R') ans=(ans+1)%INF;  //特殊情况2,只有一个R
				for(int j=1;j+i<len;j+=2){
					int r=0;
					if(a[i]=='R') r=1;
					for(int k=i+j;k<len;k+=j){
						if(a[k]=='G') break;
						if(a[k]=='R') r++;
						if(r==rall) ans=(ans+1)%INF;
					}
			    }
			}
			if(ok==0) break;        //注意,当枚举的起点是一个已经存在的R时,以这个R为起点跑一边就结束枚举
		}
		long long tmp=1;
		for(int i=0;i<num;++i) tmp=(2*tmp)%INF;
		ans=(tmp-ans+INF)%INF;
		printf("%I64d\n",ans);
	}
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2025-01-31 09:09:40

!HDU 4346 插旗子RGR的插法有多少种-思维&正难则逆&思维!的相关文章

单链表 初始化 创建 头插法 尾插法 插入 删除 查找 合并 长度

#include <stdio.h> #include <stdlib.h> #define OK 1 #define ERROR -1 #define TRUE 1 #define FALSE -1 #define NULL 0 #define OVERFLOW -2 #define ElemType int #define Status int typedef int ElemType typedef int Status #define LEN sizeof(LNode) #

单链表:头插法和尾插法

头插法: linklist *CreateList_Front() { linklist *head, *p; char ch; head = NULL; printf("依次输入字符数据(‘#’表示输入结束):\n"); ch = getchar(); while(ch != '#') { p = (linklist*)malloc(sizeof(linklist)); p->data = ch; p->next = head; head = p; ch = getcha

c语言:一只青蛙一次可以跳上1级台阶,也可以跳上2级。求该青蛙跳上一个n级的台阶总共有多少种跳法?

一只青蛙一次可以跳上1级台阶,也可以跳上2级.求该青蛙跳上一个n级的台阶总共有多少种跳法? 解:把n级台阶时的跳法记为f(n),当n>2时,第一次跳的时候有两种不同的选择:一是第一次只跳1级,此时跳法数目等于后面剩下的n-1级台阶的跳法数目,即为f(n-1);另外一种是第一次跳2级,此时跳法数目等于后面剩下的n-2级台阶的跳法数目,即为f(n-2);因此n级台阶时的跳法为f(n)=f(n-1)+f(n-2).不难看出这实际是斐波拉契数列的变形应用,把斐波拉契数列的每一项向前移动了1位. 程序:

hdu 2609 How many 最小表示法

How many Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 1248    Accepted Submission(s): 486 Problem Description Give you n ( n < 10000) necklaces ,the length of necklace will not large than 100

单链表的头插法和尾插法c语言实现

/*单链表的头插法和尾插法c语言实现*/ #include <stdio.h>#include <stdlib.h>#include <string.h>#define SIZE 100/*简单的定义一个链表节点的数据单元*/typedef struct student_t{ int num; char name[SIZE]; struct student_t* pNext;}studentList, *pStudentList; /*定义一个全局的静态的链表头节点指针

C实现头插法和尾插法来构建单链表(不带头结点)

链表的构建事实上也就是不断插入节点的过程.而节点的插入能够分为头插法和尾插法. 头插法就是在头结点后插入该节点,始终把该节点作为第一个节点.尾插法就是在链表的最后一个节点处插入元素,作为最后一个节点.假设想要了解链表的概念和其它链表操作.请參考<数据结构与算法之链表><C语言实现链表的基本操作>两篇文章.演示样例代码上传至  https://github.com/chenyufeng1991/HeadInsertAndTailInsert . // // main.c // Hea

百钱买百鸡:公鸡5元一只,母鸡3元一只,小鸡1元3只,问100元买100只鸡,问有多少种买法,输出每种买法的结果!

/** * 百钱买百鸡:公鸡5元一只,母鸡3元一只,小鸡1元3只,问100元买100只鸡,问有多少种买法,输出每种买法的结果! * */ public class Test3 { public static void main(String[] args) { int c = 0; for (int a = 0; a < 100; a++) { for (int b = 0; b < 100; b++) { if ((7 * a + 4 * b) == 100) { c++; System.o

建立链表—头插法、尾插法—有无头结点

1.建立链表-头插法-头结点 1 //建立链表-头插法-头结点 2 LinkList CreatList_head() 3 { 4 DataType x; //数据 5 LinkList p,head; //结点 6 head = (LinkList)malloc(sizeof(LNode)); 7 head->next = NULL; 8 head->data = 0; 9 10 scanf("%d",&x); 11 while(x != 999) 12 { 13

线性表的链式存储之单链表的尾插法

对单链表进行遍历.查找.插入.删除等操作,最终效果如下: 相关C代码如下: /*线性表的链式存储之单链表的尾插法*/ #include <stdio.h> #include <stdlib.h> #include <malloc.h> /*定义变量*/ typedef int DataType; typedef struct node{     //定义链表结点数据结构 DataType data; struct node * pNext; }NODE; typedef