一个解很多绝对值的题,这种题记得高中老师讲过,不能依次判断谁大于零,谁小于零,这样的复杂是2的n次方。将每一项的绝对值去掉,假设是大于零,那么公式就是x>b/a,对b/a排序,从左至右判断若当前答案在这个区间内有解,那么进行解方程,判断是否合法。
当A=0,B==C的时候就是无限解,否则是无解。
输出必须得排序后得输出。。
总结:自己在数学方面得题还是偏弱,前几场数据结构的题听到思路,一个小时左右就可以A了,这个题我写了4个小时才A,主要是样例一直过不了,一直在debug。。。
看了很多人的代码,还是许老师的代码比较容易懂
【代码】
#include
using namespace std;
typedef long long ll;
ll gcd(ll a,ll b) { return b?gcd(b,a%b):a;}
const int N=1e5+10;
int n;
ll c,suma[N],sumb[N];
struct node
{
ll a,b;
}t[N];
bool cmp(node t1,node t2)
{
return t1.b*t2.aans,G;
int main()
{
int _;cin>>_;
while(_--)
{
scanf("%d%lld",&n,&c);
for(int i=0;i<=n;++i) suma[i]=sumb[i]=0;
ans.clear();
G.clear();
int flag=0;
for(int i=1;i<=n;++i)
{
scanf("%lld%lld",&t[i].a,&t[i].b);
t[i].b=-t[i].b;
}
sort(t+1,t+1+n,cmp);
for(int i=1;i<=n;++i)
{
suma[i]=suma[i-1]+t[i].a;
sumb[i]=sumb[i-1]-t[i].b;
}
for(int i=0;i<=n;++i)
{
ll A = suma[i] - (suma[n] - suma[i]);
ll B = sumb[i] - (sumb[n] - sumb[i]);
if(!A)
{
if(c==B) flag=1;
continue;
}
ll fz=c-B,fm=A;
ll gc=gcd(fz,fm);
fz=fz/gc,fm=fm/gc;
if(fm<0) fm=-fm,fz=-fz;
int ok=1;
if(ifm*t[i+1].b)ok=0;
if(i>0&&fz*t[i].a=0;--i)
{
printf(" %lld/%lld",G[i].a,G[i].b);
}
puts("");
}
}
}
给n、k,问用1~n组成排列时,以 p[i+1]-p[i] 为字典序时第k小的字典序时的排列是多少
学习来自qingshanfly。关键在于k不大于10000,那么最多构造长度为8的排列时就可以得到答案了。
另一个重点就是当n>8时,n放在最前面,后面从1开始递增是字典序最小的。n 1 2 3 ...... n-1
【代码】
#include
using namespace std;
const int N=1e5+10;
struct node
{
int p[30];
int len;
}a[N];
int b[30];
bool cmp(node a,node b)
{
for(int i=2;i<=a.len;++i)
{
if(a.p[i]-a.p[i-1]!=b.p[i]-b.p[i-1])
return a.p[i]-a.p[i-1]>_;
while(_--)
{
int n,k;
scanf("%d%d",&n,&k);
int pos=0;
if(n<=8)
{
for(int i=1;i<=n;++i) b[i]=i;
do
{
++pos;
for(int i=1;i<=n;++i) a[pos].p[i]=b[i];
a[pos].len=n;
}while(next_permutation(b+1,b+1+n));
}
else
{
for(int i=1,j=8;i<=8;++i,--j) b[i]=n-j;
do{
++pos;
int cnt=0;
a[pos].p[++cnt]=n;
for(int i=1;i
这个题看着跟kmp类似,于是我用普通的kmp疯狂找做法,后来百度一波知道居然是扩展kmp的一道经典例题(最长公共前缀)。
没什么意思,直接贴代码会用板子就行。
#include
#define mt(a) memset(a,0,sizeof(a))
using namespace std;
typedef long long ll;
const ll mod=1e9+7;
ll extend[1000001];
ll Next[1000001];
ll min(ll x,ll y)
{
if(x>y) return y;
return x;
}
void getNext(char *t,int len)
{
mt(Next);
//ll len=t.length();
Next[0]=len;
ll a,p;
a=1;
while( a 0 ? (p - i + 1) : 0;
while(i + j < len && t[i+j] == t[j]) j++;
Next[i]=j;
a=i;
}
}
}
char s[1000100];
int main()
{
int Case;
scanf("%d",&Case);
while(Case--)
{
scanf("%s",s);
int len=strlen(s);
//exkmp(s,s,len);
getNext(s,len);
ll ans=0,num=0;
for(int i=1;i=len) num++;
}
}
printf("%lld\n",ans+len-1-num);
}
ret
给 n x y 问构造长度为n,且1到n各使用一次的方案数是多少?条件:相邻两个数之差的绝对值小于等于2,x 【题解】 当x不为1时,那1位置往右边扩展时必须得往1走去,为了能够回到x+1,唯一得构造方案就是x-2,x-4,接着回来x-3,x-1,x+1.那么这样得方案是唯一的,y也类似。 那么答案就转换为只使用 x+1,到y-1的组成排列的方案数了。那么就是一个dp方程的事了,通过简单观察可以得到递推式 dp[i]=dp[i-1]+dp[i-3](不好解释,很难讲,自己推一遍就知道了) 【代码】 #include