传说中有位神犇,居住在公元250年前的压力山大,由于神犇一贯低调,所以人们连他活了多少岁都不知道,好在XXXX文献上有段关于他生平细节的文字。。
XX神犇的一生,幼年占了1/6,又过了1/12的青春期,又谈了1/6的恋爱后结婚,m年后生了个孩子,名叫神牛,神牛比神犇先死n年,神牛的寿命是神犇的一半
现在人们邀请作为下一任神犇的你,算出这位神犇活了多少岁。。(神犇的命都是好长的)
注意
请采用下面这种格式输入
#include
using namespace std;
int main()
{
int n , m;
while(scanf("%d%d",&n,&m) != EOF)
{
}
return 0;
}
/*分析:
假定f[n]=A^n;//A为矩阵,f[n]为A^n的某项值
则sum(f[g[n]])=f[g[0]]+f[g[1]]+...+f[g[n]]
=A^b+A^(k+b)+A^(2k+b)+A^(3k+b)+...+A^(nk+b)
=A^b+A^b(A^k+A^2k+A^3k+A^4k+...+A^nk)
将A^k看成一个新的矩阵B,则原式:
=A^b+A^b(B^1+B^2+B^3+...+B^n);//A^b,A^k用矩阵快速幂求出,括号中的用二分矩阵可求
所谓二分矩阵:A^1+A^2+A^3+A^4+A^5+A^6=(A^1+A^2+A^3)+A^3(A^1+A^2+A^3)
现在问题的关键转化为如何求矩阵A:
fn=1^x * x^1 + 2^x * x^2 +...+ n^x * x^n;
fn+1=1^x * x^1 + 2^x * x^2 +...+ n^x * x^n+(n+1)^x * x^(n+1)=fn+(n+1)^x * x^(n+1),将(n+1)^x二项式展开然后用矩阵快速幂
构造矩阵:
|1 xC(x,0) xC(x,1) xC(x,2) ... xC(x,x)| |fn | |f(n+1) |
|0 xC(0,0) 0 0 ... 0 | |x^n * n^0| |x^(n+1) * (n+1)^0|
|0 xC(1,0) xC(1,1) 0 ... 0 | *|x^n * n^1|=|x^(n+1) * (n+1)^1|
|0 xC(2,0) xC(2,1) xC(2,2) ... 0 | |x^n * n^2| |x^(n+1) * (n+1)^2|
|... | |... | |... |
|0 xC(x,0) xC(x,1) xC(x,2) ... xC(x,x)| |x^n * n^x| |x^(n+1) * (n+1)^x|
*/
//第一种方法,采用二分求A^1+A^2+A^3...+A^n
#include
#include
#include
#include
#include
#include
#include
#include
too_weak的奶酪
Time Limit : 3000/1000ms (Java/Other) Memory Limit : 65535/32768K (Java/Other)
Total Submission(s) : 103 Accepted Submission(s) : 3
Font: Times New Roman | Verdana | Georgia
Font Size: ← →
Problem Description
too_weak有一块N x N的棋盘,棋盘上K只老鼠,会吃掉和它处于同一行或同一列的奶酪,现在too_weak想要在棋盘上尽可能多地放置奶酪,要使得too_weak放的奶酪不会被老鼠吃掉。现在不能更弱的too_weak想要知道有多少个位置不能放奶酪(有老鼠的位置除外)。
Input
输入数据有很多组,以EOF结尾。
每组数据以两个整数N,K。N代表棋盘的规模是N x N,K代表老鼠的数目。
接下来有K行,每行两个数x,y。分别代表每只老鼠的坐标(下标从1开始)
1. 1 <= N<= 10^9,1<=k<=10^6
2. 1<=x,y<=10^9
Output
输出不能放置奶酪的位置有多少个。(除去有老鼠的位置)
Sample Input
Sample Output
Author
moonlike
可以先统计行被占用了多少,然后在统计列时去除对应重复的,再累加。
最后化简表达式可得到如下结果:
numx表示不同的行数量
numy表示不同的列数量
answer = n*(numy+numx)-1ll*numy*numx-k
#include
#include
#include
#include
using namespace std;
const int maxn = 1000005;
int x[maxn],y[maxn];
int main()
{
int n,k;
while(~scanf("%d%d",&n,&k))
{
for(int i=0;i
Lentty要吃巧克力
Time Limit : 6000/2000ms (Java/Other) Memory Limit : 65535/32768K (Java/Other)
Total Submission(s) : 57 Accepted Submission(s) : 5
Font: Times New Roman | Verdana | Georgia
Font Size: ← →
Problem Description
Lentty最喜欢做的事情就是吃巧克力,经常幻想拥有吃不完的巧克力,作为一个acmer,kane出了个问题准备考考她,如果回答出来,那巧克力自然是源源不断的啦。kane给出了一列排好的的巧克力,有的是德芙,有的是费列罗,它们都拥有不同的美味值...现在kane通过魔法更改了这些巧克力,lentty必须能指出排列中第K个是巧克力的美味值是多少和某一段巧克力中最美味的值是多少,才能吃到巧克力,否则,哼哼,就去乖乖的做题吧。现在,lentty来寻求你的帮助,你能让poor lentty 吃上巧克力吗?
Input
输入数据有很多组,以EOF结尾。
每组数据以四个整数N,M。N代表初始的巧克力数目,M代表操作数。
第一行给定n,第二行含有n个正整数,代表每块巧克力的美味值wi。
每块巧克力的下标从0-n-1.。
操作分4种,Query x y 代表查询某一个区间内的美味最大值。
Ask x 代表查询某一块巧克力的美味值。
Change x y 代表将第x块的美味值变成y
Add x y 代表讲从第x块到第y块巧克力的美味值分别增加1.
1. 1 <= N<= 100000
2.1<= M <= 100000
2. Wi <= 5000
Output
对于每一个Query输出一个整数,代表区间内的美味最大值。
对于每一个Ask 输出一个整数,代表这块巧克力的美味值。
Sample Input
10 4
1 2 3 4 5 6 7 8 9 10
Ask 0
Change 0 1
Add 0 2
Query 0 2
Sample Output
Author
Mr.Ant
线段数的基本操作:单点更新,区间更新与最值查询。
#include
#include
#include
#include
using namespace std;
#define lz 2*u,l,mid
#define rz 2*u+1,mid+1,r
const int maxn=100005;
int a[maxn];
int maxx[4*maxn], flag[4*maxn];
void push_down(int u, int l, int r)
{
if(flag[u])
{
flag[2*u]+=flag[u];
flag[2*u+1]+=flag[u];
maxx[2*u]+=flag[u];
maxx[2*u+1]+=flag[u];
flag[u]=0;
}
}
void build(int u, int l, int r)
{
flag[u]=0;
if(l==r)
{
maxx[u]=a[l];
return ;
}
int mid=(l+r)>>1;
build(lz);
build(rz);
maxx[u]=max(maxx[2*u],maxx[2*u+1]);
}
void Update(int u, int l, int r, int tl, int tr, int c, int op)
{
if(tl<=l&&r<=tr)
{
if(op==1)
{
flag[u]+=c;
maxx[u]+=c;
}
else
{
maxx[u]=c;
}
return ;
}
push_down(u,l,r);
int mid=(l+r)>>1;
if(tr<=mid) Update(lz,tl,tr,c,op);
else if(tl>mid) Update(rz,tl,tr,c,op);
else
{
Update(lz,tl,mid,c,op);
Update(rz,mid+1,tr,c,op);
}
maxx[u]=max(maxx[2*u],maxx[2*u+1]);
}
int Query(int u, int l, int r, int tl, int tr)
{
if(tl<=l&&r<=tr) return maxx[u];
push_down(u,l,r);
int mid=(l+r)>>1;
if(tr<=mid) return Query(lz,tl,tr);
else if(tl>mid) return Query(rz,tl,tr);
else
{
int t1=Query(lz,tl,mid);
int t2=Query(rz,mid+1,tr);
return max(t1,t2);
}
}
int main()
{
int n, m;
while(cin >> n >> m)
{
for(int i=1; i<=n; i++) scanf("%d",a+i);
build(1,1,n);
for(int i=1; i<=m; i++)
{
char ch[10];
int x, y;
scanf("%s",ch);
if(strcmp(ch,"Add")==0)
{
scanf("%d%d",&x,&y);
x++, y++;
Update(1,1,n,x,y,1,1);
}
else if(strcmp(ch,"Change")==0)
{
scanf("%d%d",&x,&y);
x++;
Update(1,1,n,x,x,y,2);
}
else if(strcmp(ch,"Ask")==0)
{
scanf("%d",&x);
x++;
printf("%d\n",Query(1,1,n,x,x));
}
else
{
scanf("%d%d",&x,&y);
x++,y++;
printf("%d\n",Query(1,1,n,x,y));
}
}
}
return 0;
}
拯救之路
Time Limit : 3000/1000ms (Java/Other) Memory Limit : 65535/32768K (Java/Other)
Total Submission(s) : 14 Accepted Submission(s) : 0
Font: Times New Roman | Verdana | Georgia
Font Size: ← →
Problem Description
在忍者的世界里有众多的忍者村,鸣人和佐助出生在木叶村,他们从小一起学习忍术,但是佐助为了获得更强的力量离开了木叶村投奔了邪恶的大蛇丸。鸣人为了不让佐助被邪恶的力量所控制,决定只身前往大蛇丸的根据地拯救他。这里有n个忍者根据地,木叶村位于根据地1,大蛇丸位于根据地n,然后有m条双向的道路连接这n个根据地,每条路有一个特定的长度L。因为大蛇丸忍术高深,所以拯救之路注定不安逸。大蛇丸对每条路都施了一种忍术,每条路都用一个特定的字符标注(‘F’,‘U’,‘C’,‘K’中的一种),因此每条路鸣人只能按照特定的路线走方可到达大蛇丸的巢穴拯救佐助,鸣人走的路线必须是按照以下序列 ‘F’->’U’->’C’->’K’->’F’->’U’->’C’->’K’->.... etc,否则他是达到不了大蛇丸的巢穴的。为了让拯救之路更艰难,大蛇丸又施加了一种忍术,到达大蛇丸根据地时必须是走的完整的一个或者多个“FUCK”序列,这样才能拯救成功。
Note:为了让拯救行动更加容易,应该让拯救路线尽量短,同时应该让“FUCK”序列尽量长。
Input
第一行输入一个整数T(1<=T<=500),表示测试数据的组数。
每组测试数据有两个整数n(1<=n<=1500),m(1<=m<=20000),表示n个忍者根据地和m条道路。
接下来输入m行,每行有4个变量 “u v L c”,表示这是一条路介于根据地u,v(1<=u,v<=n),这条路的长度是L(1<=L<=1000000),c是一个标记字符(‘F’,‘U’,‘C’,‘K’中的一种)。
Output
如果拯救行动无法完成,请输出Impossible。否则输出拯救路线的长度以及走过的“FUCK”序列个数。
Sample Input
2
4 4
1 2 1 F
2 1 1 U
1 3 1 C
3 4 1 K
4 4
1 2 1 F
2 3 1 U
3 4 1 C
4 1 1 K
Sample Output
Author
Mr.Ant
#include
#include
#include
#include
using namespace std;
typedef long long lld;
const int mn=3333;
const int mm=44444;
const lld oo=1e15;
int reach[mm], next[mm], flow[mm], ch[mm];
lld head[mn], que[mn], dis[mn][4], cnt[mn][4], inque[mn];
int n, edge;
void addedge(int u, int v, int c1, int c2, char c)
{
ch[edge]=c, reach[edge]=v, flow[edge]=c1, next[edge]=head[u], head[u]=edge++;
ch[edge]=c, reach[edge]=u, flow[edge]=c2, next[edge]=head[v], head[v]=edge++;
}
int find(char c)
{
if(c=='F') return 0;
else if(c=='U') return 1;
else if(c=='C') return 2;
else return 3;
}
bool spfa()
{
int l=0, h=0;
memset(inque,0,sizeof(inque));
for(int i=1; i<=n; i++)
for(int j=0; j<4; j++) dis[i][j]=oo, cnt[i][j]=0;
inque[1]=1;
dis[1][0]=0;
que[l++]=1;
while(l!=h)
{
int u=que[h++];
if(h==mn) h=0;
inque[u]=0;
for(int i=head[u]; i>=0; i=next[i])
{
int s=find(ch[i]), v=reach[i], val=flow[i];
if(dis[v][(s+1)%4]>=dis[u][s]+val)
{
if(dis[v][(s+1)%4]==dis[u][s]+val)
{
if(cnt[u][s]+1>cnt[v][(s+1)%4]) cnt[v][(s+1)%4]=cnt[u][s]+1;
else continue;
}
else
{
dis[v][(s+1)%4]=dis[u][s]+val;
cnt[v][(s+1)%4]=cnt[u][s]+1;
}
if(!inque[v])
{
inque[v]=1;
que[l++]=v;
if(l==mn) l=0;
}
}
}
}
if(dis[n][0]==oo||!cnt[n][0]) return false;
else return true;
}
int main()
{
// freopen("in.txt","r",stdin);
// freopen("out.txt","w",stdout);
int m, T, tcase=0;
cin >> T;
while(T--)
{
cin >> n >> m;
edge=0;
memset(head,-1,sizeof(head));
int mp[4]={0,0,0,0}, ct=0;
while(m--)
{
int u, v, val, se;
char sh[3];
scanf("%d%d%d%s",&u,&v,&val,sh);
addedge(u,v,val,val,sh[0]);
if(n==1&&u==1&&v==1)
{
se=find(sh[0]);
if(!mp[se]) ct++, mp[se]=val;
else mp[se]=min(mp[se],val);
}
}
if(ct==4)
{
lld sum=mp[0]+mp[1]+mp[2]+mp[3];
printf("%I64d %d\n",sum,ct/4);
continue;
}
bool ok=spfa();
if(!ok) puts("Impossible");
else printf("%I64d %I64d\n",dis[n][0],cnt[n][0]/4);
}
return 0;
}
ZEROm的乘法运算
Time Limit : 3000/1000ms (Java/Other) Memory Limit : 65535/32768K (Java/Other)
Total Submission(s) : 24 Accepted Submission(s) : 1
Font: Times New Roman | Verdana | Georgia
Font Size: ← →
Problem Description
ZEROm要too_weak快速计算下列程序的运算结果Sum,too_weak必然是不会的,现在请你帮助他.
int Sum=0;
for(int i=1;i<=N;i++)
for(int j=i+1;j<=N;j++)
for(int k=j+1;k<=N;k++)
Sum+=a[i]*a[j]*a[k];
Input
输入数据有很多组,以EOF结尾。(大规模输入。请用scanf)
每组数据的第一行包含一个正整数N(1 <= N<= 1000000),说明第二行有N个数。
第二行有N个数,分别代表a[1],a[2],a[3]....a[N].(0<=a[i]<=10^9)
Output
因为Sum可能很大,输出Sum对9973求余的结果。
Sample Input
Sample Output
Author
moonlike
容斥原理的简单应用。
#include
using namespace std;
typedef long long LL;
const int mod = 9973;
const int maxn =1000000+5;
LL a[maxn];
int main()
{
int n;
while(~scanf("%d",&n)){
LL sum=0,xxx=0;
for(int i=0;i