FOJ 10月赛题 FOJ2198~2204
A题。
发现是递推可以解决这道题,a[n]=6*a[n-1]-a[n-2]。因为是求和,可以通过一个三维矩阵加速整个计算过程,主要是预处理出2^k时的矩阵,可以通过这道题
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define LL long long
using namespace std; const int MOD=1e9+; int quick(int a,int b){
int res=;
while(b){
if(b&){
res+=a;
if(res>=MOD) res-=MOD;
}
b>>=;
a+=a;
if(a>=MOD) a-=MOD;
// cout<<"YES"<<endl;
}
return res;
} struct Matrix{
int a[][];
void init(){
for(int i=;i<;i++)
for(int j=;j<;j++) a[i][j]=;
}
/* Matrix operator= (Matrix p){
for(int i=0;i<3;i++){
for(int j=0;j<3;j++) a[i][j]=p.a[i][j];
}
return *this;
}*/
Matrix operator* (Matrix s){
Matrix res;
for(int i=;i<;i++)
for(int j=;j<;j++){
res.a[i][j]=;
for(int k=;k<;k++){
res.a[i][j]+=(long long)a[i][k]*s.a[k][j]%MOD;
if(res.a[i][j]>=MOD) res.a[i][j]-=MOD;
/// cout<<"YES"<<endl;
}
}
return res;
}
}a,power[]; void init(){
power[].a[][]=,power[].a[][]=,power[].a[][]=;
power[].a[][]=,power[].a[][]=,power[].a[][]=;
power[].a[][]=,power[].a[][]=MOD-,power[].a[][]=; a.a[][]=,a.a[][]=,a.a[][]=;
a.a[][]=,a.a[][]=,a.a[][]=;
a.a[][]=,a.a[][]=,a.a[][]=; for(LL i=;i<;i++){
power[i]=power[i-]*power[i-];
}
/* for(int i=0;i<3;i++){
for(int j=0;j<3;j++)
cout<<power[0].a[i][j]<<" ";
cout<<endl;
}*/
} int main(){
init();
int T;LL n;
scanf("%d",&T);
while(T--){
scanf("%I64d",&n); /////不能用lld
Matrix ans=a;
int cnt=;
while(n){
if(n&) ans=ans*power[cnt];
n>>=;
cnt++;
}
printf("%d\n",ans.a[][]);
} return ;
}
B题。留坑
C题。这道题其实和G题一样,DP可以解决。记录前两个位置的状态,限制第三个位置的状态,进行转移即可。因为是一个环,所以,在选择最后两个位置的状态时要和最开始的两个位置相容,进行枚举即可。所以要计算四种开始的状态,分别是(00),(01)(10)(11)。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm> using namespace std; int dp[][][][][][];//////fisrt ,second
const int MOD=1e9+; int add(int a,int b){
a+=b;
if(a>MOD) a-=MOD;
return a;
} int main(){
int T,n,p;
scanf("%d",&T);
memset(dp,,sizeof(dp));
dp[][][][][][]=dp[][][][][][]=dp[][][][][][]=dp[][][][][][]=;
for(int fst=;fst<;fst++){
for(int sec=;sec<;sec++){
for(int i=;i<=;i++){
for(int k=;k<=min(i,);k++){
///select
if(k){
dp[fst][sec][i][k][][]=add(dp[fst][sec][i][k][][],dp[fst][sec][i-][k-][][]);
dp[fst][sec][i][k][][]=add(dp[fst][sec][i][k][][],dp[fst][sec][i-][k-][][]);
}
///un select
dp[fst][sec][i][k][][]=add(dp[fst][sec][i][k][][],add(dp[fst][sec][i-][k][][],dp[fst][sec][i-][k][][]));
dp[fst][sec][i][k][][]=add(dp[fst][sec][i][k][][],add(dp[fst][sec][i-][k][][],dp[fst][sec][i-][k][][]));
}
}
}
}
while(T--){
scanf("%d%d",&n,&p);
int ans=;
for(int fst=;fst<;fst++){
for(int sec=;sec<;sec++){
for(int i=;i<;i++){
for(int j=;j<;j++){
if(!(fst&i)&&!(sec&j)){
ans=add(ans,dp[fst][sec][n][p][i][j]);
ans=add(ans,dp[fst][sec][n][p][i][j]);
}
}
}
}
}
printf("%d\n",ans);
}
return ;
}
D题。这道题是学习窝bin的。线段树可以解决。
首先,要知道的是gcd(a1,a2)=gcd(a1,a1-a2)。则gcd(x-a1,x-a2)=gcd(x-a1,a1-a2)。
那么,对于gcd(x-a1,x-a2,x-a3.....x-an)=gcd(x-a1,a1-a2,a2-a3.....a[n-1]-a[n])。使用线段树来维护a1-a2,a2-a3....这个差分序列,同时记录x的值以及头尾两个a1,an的值。使用线段树更新,即可。具体可看代码.
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <string>
#include <math.h>
#include <stdlib.h>
#include <time.h>
using namespace std;
const int MAXN = ;
long long gcd(long long a,long long b){
if(b == )return a;
return gcd(b,a%b);
}
struct Node {
int l,r;
int a,b;
int first,last;
int g;
int val;
}segTree[MAXN<<];
void push_up(int i) {
segTree[i].first = segTree[i<<].first;
segTree[i].last = segTree[(i<<)|].last;
segTree[i].val = gcd(segTree[i<<].val,segTree[(i<<)|].val);
segTree[i].val = gcd(segTree[i].val,abs(segTree[i<<].last-segTree[(i<<)|].first));
segTree[i].g = gcd(segTree[i].val,segTree[i].first);
}
void Update_node(int i,int a,int b) {
segTree[i].first = a*segTree[i].first+b;
segTree[i].last = a*segTree[i].last+b;
segTree[i].g = gcd(segTree[i].first,segTree[i].val);
segTree[i].a *= a;
segTree[i].b = a*segTree[i].b+b;
}
void push_down(int i) {
if(segTree[i].l == segTree[i].r)return;
int a = segTree[i].a;
int b = segTree[i].b;
if(a != || b != ) {
Update_node(i<<,a,b);
Update_node((i<<)|,a,b);
a = ;
b = ;
}
}
int a[MAXN];
void build(int i,int l,int r) {
segTree[i].l = l;
segTree[i].r = r;
segTree[i].a = ;
segTree[i].b = ;
if(l == r) {
segTree[i].first = a[l];
segTree[i].last = a[l];
segTree[i].val = ;
segTree[i].g = a[l];
return;
}
int mid = (l+r)/;
build(i<<,l,mid);
build((i<<)|,mid+,r);
push_up(i);
}
void update(int i,int l,int r,int a,int b) {
if(segTree[i].l == l && segTree[i].r == r) {
Update_node(i,a,b);
return;
}
push_down(i);
int mid = (segTree[i].l+segTree[i].r)/;
if(r <= mid)update(i<<,l,r,a,b);
else if(l > mid)update((i<<)|,l,r,a,b);
else {
update(i<<,l,mid,a,b);
update((i<<)|,mid+,r,a,b);
}
push_up(i);
}
int query(int i,int l,int r) {
if(segTree[i].l == l && segTree[i].r == r)
return segTree[i].g;
push_down(i);
int mid = (segTree[i].l+segTree[i].r)/;
if(r <= mid)return query(i<<,l,r);
else if (l > mid)return query((i<<)|,l,r);
else return gcd(query(i<<,l,mid),query((i<<)|,mid+,r));
} int main(){
int n,m;
while(scanf("%d%d",&n,&m) == ) {
for(int i = ;i <= n;i++)scanf("%d",&a[i]);
build(,,n);
int op;
int l,r,x;
while(m--) {
scanf("%d",&op);
if(op == ) {
scanf("%d%d%d",&l,&r,&x);
update(,l,r,-,x);
} else {
scanf("%d%d",&l,&r);
printf("%d\n",query(,l,r));
}
}
}
return ;
}
E题推理。这里注意必须从说+号的人下手。由于有m个人说真话,假设说了+A的人都说了真话,那么-A的人就是假话,而说其他的+的人也说了假话,说其他-的人说了真话。这里统计说了真话的人,如果>m,则说了+A的人都说了假话。如果刚好,我们统计这种“刚好”有多少种,置为待定状态,把iscrime[A]=true。则对于说了A是罪犯的人,因无法判断A是否真的是罪犯,输出未定。如果iscrime[A]=false,对于说了A是罪犯的,则肯定是说了假话。对于A不是罪犯的,如果这时A是true,因为A未定,所以输出待定,否则,如果A是false,则肯定是说了真话,因为对于iscrime[A]=false的条件,只有当说真话的人肯定说了假话,亦即是说了+A的人肯定说了假话,才会是false。
由于题目条件是肯定有解,所以如果“刚好”的情况只有一种,则谁说真谁说假是可以确定的。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm> using namespace std; const int MAX=1e5+; int say[MAX],vote[MAX],nvote[MAX],pcnt,ncnt;
bool iscrime[MAX]; int main(){
int T,n,m;
scanf("%d",&T);
while(T--){
pcnt=ncnt=;
scanf("%d%d",&n,&m);
memset(vote,,sizeof(vote));
memset(nvote,,sizeof(nvote));
for(int i=;i<=n;i++){
scanf("%d",&say[i]);
if(say[i]>) vote[say[i]]++;
else nvote[-say[i]]++;
if(say[i]>) pcnt++;
else ncnt++;
}
memset(iscrime,false,sizeof(iscrime));
int counts=;
for(int i=;i<=n;i++){
if(vote[i]+ncnt-nvote[i]==m){
iscrime[i]=true;
counts++;
}
}
if(counts==){
int find;
for(int i=;i<=n;i++){
if(say[i]>)
if(iscrime[say[i]]){
puts("Truth");
}
else puts("Lie");
else{
if(iscrime[-say[i]]){
puts("Lie");
}
else puts("Truth");
}
}
}
else{
for(int i=;i<=n;i++){
if(say[i]>){
if(iscrime[say[i]]){
puts("Not defined");
}
else puts("Lie");
}
else{
if(iscrime[-say[i]]){
puts("Not defined");
}
else puts("Truth");
}
}
} }
return ;
}
F题使用set就可以解决了。
G题,DP题。和C题是一样的。先枚举DP假如是一条直线时,连续的个数<=6个时的所有情况。再按这种方式枚举,减去因为首尾相连可能出现>=7的情况,就可以得到结果.
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std; const int MAX=;
const int MOD=;
int dp[MAX][][]; int main(){
int n,T,icase=;
scanf("%d",&T);
while(T--){
scanf("%d",&n);
printf("Case #%d: ",++icase);
if(n<){
int ans=;
for(int i=;i<=n;i++)
ans*=;
// if(n==7) ans-=2;
printf("%d\n",ans%MOD);
continue;
}
memset(dp,,sizeof(dp));
dp[][][]=; dp[][][]=;
for(int i=;i<=n;i++){
for(int j=;j<=;j++)
for(int k=;k<=;k++){
if(k==){
///dp[i][j][k]=0;
for(int p=;p<=;p++)
dp[i][j][k]+=dp[i-][j^][p];
dp[i][j][k]%=MOD;
}
else{
//dp[i][j][k]=0;
dp[i][j][k]+=dp[i-][j][k-];
dp[i][j][k]%=MOD;
}
}
}
int ans=;
for(int j=;j<=;j++){
for(int k=;k<=;k++){
ans+=dp[n][j][k];
}
ans%=MOD;
}
// cout<<ans<<endl;
memset(dp,,sizeof(dp));
for(int e=;e<=;e++){
dp[e+][][]=;
for(int i=e+;i<=n;i++){
for(int j=;j<=;j++)
for(int k=;k<=;k++){
if(k==){
// dp[i][j][k]=0;
for(int p=;p<=;p++)
dp[i][j][k]+=dp[i-][j^][p];
dp[i][j][k]%=MOD;
}
else{
// dp[i][j][k]=0;
// for(int p=1;p<k;p++)
dp[i][j][k]+=dp[i-][j][k-];
dp[i][j][k]%=MOD;
}
}
}
for(int p=-e;p<=;p++)
ans-=(dp[n][][p])*;
ans%=MOD;
memset(dp,,sizeof(dp));
}
printf("%d\n",(ans%MOD+MOD)%MOD);
}
return ;
}
FOJ 10月赛题 FOJ2198~2204的更多相关文章
- EOJ2018.10 月赛
EOJ2018.10 月赛 题目一览表(Green color indicate understand and Accept) 来源 考察知识点 完成时间 A oxx 的小姐姐们 EOJ 数学+思维 ...
- python+java蓝桥杯ACM日常算法题训练(一)10基础题
目录 1.简单的a+b 2.第一个HelloWorld程序! 3.三个数最大值 4.密码破译 5.母牛的故事 6.7.8.9.10 @(这里写自定义目录标题) 算法题训练网站:http://www.d ...
- FOJ有奖月赛-2016年8月(daxia专场之过四题方有奖)
http://acm.fzu.edu.cn/contest/list.php?cid=152 主要是a题, lucas定理, 就这一版能过.. 记录一下代码, 另外两个最短路 一个模拟,没什么记录 ...
- EOJ2018.10 月赛(B 数学+思维题)
传送门:Problem B https://www.cnblogs.com/violet-acmer/p/9739115.html 题意: 找到最小的包含子序列a的序列s,并且序列s是 p -莫干山序 ...
- EOJ2018.10 月赛(A 数学+思维题)
传送门:Problem A https://www.cnblogs.com/violet-acmer/p/9739115.html 题意: 能否通过横着排或竖着排将 1x p 的小姐姐填满 n x m ...
- AtCoder Grand Contest 1~10 做题小记
原文链接https://www.cnblogs.com/zhouzhendong/p/AtCoder-Grand-Contest-from-1-to-10.html 考虑到博客内容较多,编辑不方便的情 ...
- HDU 4704 Sum (2013多校10,1009题)
Sum Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)Total Submi ...
- HDU 4699 Editor (2013多校10,1004题)
Editor Time Limit: 3000/2000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)Total Su ...
- HDU 4705 Y (2013多校10,1010题,简单树形DP)
Y Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)Total Submiss ...
随机推荐
- Elasticsearch之CURL命令的PUT和POST对比
PUT是幂等方法,而POST并不是. PUT用于更新操作,POST用于新增操作比较合适. PUT,DELETE操作是幂等的,所谓幂等就是指不管进行多少次操作,结果都一样. 比如,我用PUT修改一篇文章 ...
- 阿里云虚拟主机针对恶意频繁攻击式访问造成CPU爆满的解决方法
最近网站CPU经常爆满,到阿里云提交了工单,工程师给我的处理意见: 您好,虚拟主机CPU占用比较高通常这种情况有两种可能: 一是网站应用程序代码逻辑较复杂,或业务架构效率比较低,在请求了某个网 ...
- Android 检查手机上是否安装了指定的软件(根据包名检测)
Android检查手机上是否安装了指定的软件(根据包名检测) /** * 检查手机上是否安装了指定的软件 * @param context * @param packageName * @return ...
- CSS——img标签消除3px
1.dispaly:block 2.float:left 这两种都可以消除3px
- [Windows Server 2008] 查看PHP详细错误信息
★ 欢迎来到[护卫神·V课堂],网站地址:http://v.huweishen.com ★ 护卫神·V课堂 是护卫神旗下专业提供服务器教学视频的网站,每周更新视频. ★ 本节我们将带领大家:查看IIS ...
- Git 分支创建
分支策略:git上始终保持两个分支,master分支与develop分支.master分支主要用于发布时使用,而develop分支主要用于开发使用. 创建master的分支developgit che ...
- 【译】x86程序员手册01
Intel 80386 Reference Programmer's Manual 80386程序员参考手册 Chapter 1 -- Introduction to the 80386 第1章 - ...
- Mac OS 小知识
删除Mac OS输入法中自动记忆的用户词组 有时候不小心制造了一个错误的词组,结果也被输入法牢牢记住,这时候可以用shift+delete组合键来删除 快捷键拾遗 Fn+Delet ...
- 【sqli-labs】 less54 GET -Challenge -Union -10 queries allowed -Variation1 (GET型 挑战 联合查询 只允许10次查询 变化1)
尝试的次数只有10次 http://192.168.136.128/sqli-labs-master/Less-54/index.php?id=1' 单引号报错,错误信息没有显示 加注释符页面恢复正常 ...
- java实例1
1.满天星星 import java.awt.*; public class xinxin { public static void main(String[] args) { Frame w = n ...