题目:Codeforces Round #175 (Div. 2)
A Slightly Decreasing Permutations
求 : n的全排列,满足有k组相邻的数字满足p(i)>p(i+1)
思路:先逆序输出最后k个数字,然后正序输出剩下的,这种情况满足。
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <cstdio>
using namespace std;
int a[100001];
int main()
{
int n,k;
scanf("%d%d",&n,&k);
for(int i=1;i<=n;i++)
a[i]=i;
for(int i=n;i>=n-k+1;i--)
printf("%d ",a[i]);
for(int i=1;i<n-k;i++)
printf("%d ",a[i]);
printf("%d\n",n-k);
return 0;
}
求:从 s 到 t ,中间至少需要多少次。
思路:从 s 出发,如果回到刚才走过的点,就进入死循环了,如果到达 t ,就输出长度 ,可以通过数组标记看是否进入死循环,我是判断这个长度超过n的时候break
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <cstdio>
using namespace std;
int a[100001];
int main()
{
int n,s,t;
scanf("%d%d%d",&n,&s,&t);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
if(s==t)
{
printf("0\n");
return 0;
}
int ans=0;
int tag=1;
while(s!=t)
{
ans++;
if(s==a[s])
{
tag=0;
break;
}
s=a[s];
if(ans>100000)
{
tag=0;
break;
}
}
if(!tag)
printf("-1\n");
else
printf("%d\n",ans);
return 0;
}
C: Building Permutation
求:由给定的一串数字,变成n的全排列,所需要加或减的数字总和
思路:直接sort后求与a[i]=i的排列的差的绝对值之和
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <cstdio>
using namespace std;
int a[300010];
int main()
{
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
long long ans=0;
sort(a+1,a+n+1);
for(int i=1;i<=n;i++)
ans+=abs(a[i]-i);
printf("%I64d\n",ans);
return 0;
}
D : Permutation Sum
求:两个全排列之和也是一个全排列的方案数
思路:一共16个数字,打表。。。。发现n是偶数时,结果是0,用了一个 next_permutation 打表,打到 n=11花了好久,估计打到n=13 就是几百倍的时间,然后n=15时,就基本上打不出来了,吭啊。
网上有对半搜索的 http://www.cnblogs.com/chenhuan001/archive/2013/04/15/3022476.html n=15的那组几十秒就打出来了,膜拜
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <cstdio>
using namespace std;
#define mod 1000000007
int main()
{
int a[17]={0,1,0,18,0,1800,0,670320,0,734832000,0,890786230,0,695720788,0,150347555,0};
int n;
scanf("%d",&n);
printf("%d\n",a[n]);
return 0;
}
E : Positions in Permutations
思路: DP ?
不会
题目:Codeforces Round #183 (Div. 2)
思路:暴力
尼玛,开始做的时候想复杂了,记着之前的一个结论,a和b中至少有一个数字是3的倍数,然后就想复杂了,改来改去,还是改成水过了
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <iostream>
#include <cmath>
using namespace std;
bool is_ok(int n)
{
int cnt=(int)sqrt(n);
cnt*=cnt;
if(cnt==n)
return 1;
return 0;
}
int main()
{
int n;
scanf("%d",&n);
int ans=0;
for(int i=1;i<=n;i++)
for(int j=i+1;j<=n;j++)
{
if(i*i+j*j>n*n)
break;
if(is_ok(i*i+j*j))
ans++;
}
printf("%d\n",ans);
return 0;
}
B: Calendar
思路:开始想用用java水过,结果发现第二组数据就跪了,这不科学啊。
实在没办法改用c++暴力了
#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <map>
using namespace std;
int month[13]={0,31,29,31,30,31,30,31,31,30,31,30,31};
bool is_leap(int n)
{
if(n%4==0)
{
if(n%100==0)
{
if(n%400==0)
return 1;
return 0;
}
return 1;
}
return 0;
}
int main()
{
int ya,yb,ma,mb,da,db;
scanf("%d:%d:%d",&ya,&ma,&da);
scanf("%d:%d:%d",&yb,&mb,&db);
int ans=0;
if(ya>yb||(ya==yb&&ma>mb)||(ya==yb&&ma==mb&&da>db))
{
swap(ya,yb);
swap(ma,mb);
swap(da,db);
}
while(ya!=yb||ma!=mb||da!=db)
{
ans++;
da++;
if(is_leap(ya))
month[2]=29;
else
month[2]=28;
if(da>month[ma])
{
da%=month[ma];
ma++;
}
if(ma>12)
{
ma%=12;
ya++;
}
}
printf("%d\n",ans);
return 0;
}
比赛之后还是不甘心java为什么第二组数据我电脑里运行的没问题,提交之后就wa了,郁闷了好久 = =
看别人用 java 过的代码 ,貌似就比我多一行语句 ft.setTimeZone(TimeZone.getTimeZone("UTC"));
唉 这个是因为时区问题导致WA的 ? 尼玛
= = 再也不用 java 装逼了 (上次写一个java做题TLE) 一用就跪 这不科学啊
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Scanner;
import java.util.TimeZone;
public class a{
public static long getQuot(String time1, String time2){
long quot = 0;
SimpleDateFormat ft = new SimpleDateFormat("yyyy:MM:dd");
ft.setTimeZone(TimeZone.getTimeZone("UTC"));
try {
Date date1 = ft.parse( time1 );
Date date2 = ft.parse( time2 );
quot = date1.getTime() - date2.getTime();
quot = quot / (1000 * 60 * 60 * 24);
} catch (ParseException e) {
e.printStackTrace();
}
return quot;
}
public static void main(String[] args) throws Exception {
Scanner r = new Scanner(System.in);
String date1 = r.nextLine();
String date2 = r.nextLine();
long day = getQuot(date2,date1);
System.out.println(Math.abs(day));
}
}
C: Lucky Permutation Triple
求:两个全排列对应位置的和产生一个新的全排列
直接输出0~n-1 和 0~n-1
然后第三行输出 和对n取余的结果
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
using namespace std;
int main()
{
int n;
scanf("%d",&n);
if(n%2==0)
printf("-1\n");
else
{
for(int i=0;i<n-1;i++)
printf("%d ",i);
printf("%d\n",n-1);
for(int i=0;i<n-1;i++)
printf("%d ",i);
printf("%d\n",n-1);
for(int i=0;i<n-1;i++)
printf("%d ",i*2%n);
printf("%d\n",(2*n-2)%n);
}
return 0;
}
D: Rectangle Puzzle II
求:满足比列是 a:b的矩形内含某个点
思路:求gcd将比例简化之后,求出矩形的大小,然后移动
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <cstdio>
using namespace std;
int gcd(int a,int b)
{
if(b==0)
return a;
return gcd(b,a%b);
}
int main()
{
int m,n,x,y,a,b;
scanf("%d%d%d%d%d%d",&m,&n,&x,&y,&a,&b);
int ggcd=gcd(a,b);
a/=ggcd;
b/=ggcd;
int tmp=min(m/a,n/b);
int width=tmp*a;
int length=tmp*b;
int x1,x2,y1,y2;
if(width&1)
{
x1=x-width/2-1;
x2=x1+width;
}
else
{
x1=x-width/2;
x2=x1+width;
}
if(length&1)
{
y1=y-length/2-1;
y2=y1+length;
}
else
{
y1=y-length/2;
y2=y+length/2;
}
if(x1<0)
{
x2-=x1;
x1=0;
}
if(y1<0)
{
y2-=y1;
y1=0;
}
if(x2>m)
{
x1-=(x2-m);
x2=m;
}
if(y2>n)
{
y1-=(y2-n);
y2=n;
}
printf("%d %d %d %d\n",x1,y1,x2,y2);
return 0;
}
求:n个数,在能去掉k个数的情况下,求最小的mod,使得所有的数字能够刚好取余编号
不会